Latest Swift 5.O

Swift 5.0 is the next major release of Swift, and brings ABI stability at long last.

!. A standard Result type

enum NetworkError: Error {
case badURL
}
import Foundationfunc fetchUnreadCount(from urlString: String, 
completion: @escaping (Result<Int, NetworkError>) -> Void) {
guard let url = URL(string: urlString) else {
completion(.failure(.badURL))
return
}
// Networking code goes here..
print("Fetching \(url.absoluteString)...")
completion(.success(1))
}
fetchUnreadCount(from: "https://myserver.erbittuu.com/api/v1/unread") { result in
switch result {
case .success(let count):
print("\(count) unread messages.")
case .failure(let error):
print(error.localizedDescription)
}
}
if let count = try? result.get() {
print("\(count) unread messages.")
}
let result = Result { try String(contentsOfFile: someFile) }

!!. Raw strings

let demoString = #"Let's try "raw string" example from "Swift 5.0""#
let keypaths = #"Swift keypaths such as \Person.name hold uninvoked references to properties."#
let answer = 42
let dontpanic = #"The answer to life, the universe, and everything is \#(answer)."#
let str = ##"I got new swift “woow”#Swift5.0"##
let multiline = #"""
The answer to life,
the universe,
and everything is \#(answer).
"""#
let regex1 = "\\\\[A-Z]+[A-Za-z]+\\.[a-z]+"
let regex2 = #"\\[A-Z]+[A-Za-z]+\.[a-z]+"#

!!!. Customizing string interpolation

struct User {
var name: String
var age: Int
}
extension String.StringInterpolation {
mutating func appendInterpolation(_ value: User) {
appendInterpolation("My name is \(value.name) and I'm \(value.age)")
}
}
let user = User(name: "Thanos", age: 1000)
print("User details: \(user)")
extension String.StringInterpolation {
mutating func appendInterpolation(_ number: Int, style: NumberFormatter.Style) {
let formatter = NumberFormatter()
formatter.numberStyle = style
if let result = formatter.string(from: number as NSNumber) {
appendLiteral(result)
}
}
}
let number = Int.random(in: 0...100)
let lucky = "The lucky number this week is \(number, style: .spellOut)."
print(lucky)
extension String.StringInterpolation {
mutating func appendInterpolation(repeat str: String, _ count: Int) {
for _ in 0 ..< count {
appendLiteral(str)
}
}
}
print("Baby shark \(repeat: "doo ", 6)")
extension String.StringInterpolation {
mutating func appendInterpolation(_ values: [String], empty defaultValue: @autoclosure () -> String) {
if values.count == 0 {
appendLiteral(defaultValue())
} else {
appendLiteral(values.joined(separator: ", "))
}
}
}
let names = ["Harry", "Ron", "Hermione"]
print("List of students: \(names, empty: "No one").")
struct HTMLComponent: ExpressibleByStringLiteral, ExpressibleByStringInterpolation, CustomStringConvertible {
struct StringInterpolation: StringInterpolationProtocol {
// start with an empty string
var output = ""
// allocate enough space to hold twice the amount of literal text
init(literalCapacity: Int, interpolationCount: Int) {
output.reserveCapacity(literalCapacity * 2)
}
// a hard-coded piece of text – just add it
mutating func appendLiteral(_ literal: String) {
print("Appending \(literal)")
output.append(literal)
}
// a Twitter username – add it as a link
mutating func appendInterpolation(twitter: String) {
print("Appending \(twitter)")
output.append("<a href=\"https://twitter/\(twitter)\">@\(twitter)</a>")
}
// an email address – add it using mailto
mutating func appendInterpolation(email: String) {
print("Appending \(email)")
output.append("<a href=\"mailto:\(email)\">\(email)</a>")
}
}
// the finished text for this whole component
let description: String
// create an instance from a literal string
init(stringLiteral value: String) {
description = value
}
// create an instance from an interpolated string
init(stringInterpolation: StringInterpolation) {
description = stringInterpolation.output
}
}
let text: HTMLComponent = "You should follow me on Twitter \(twitter: "twostraws"), or you can email me at \(email: "paul@hackingwithswift.com")."
print(text)

!V. Dynamically callable types

let result = random(numberOfZeroes: 3)
let result = random.dynamicallyCall(withKeywordArguments: ["numberOfZeroes": 3])
func dynamicallyCall(withArguments args: [Int]) -> Doublefunc dynamicallyCall(withKeywordArguments args: KeyValuePairs<String, Int>) -> Double
struct RandomNumberGenerator {
func generate(numberOfZeroes: Int) -> Double {
let maximum = pow(10, Double(numberOfZeroes))
return Double.random(in: 0...maximum)
}
}
@dynamicCallable
struct RandomNumberGenerator {
func dynamicallyCall(withKeywordArguments args: KeyValuePairs<String, Int>) -> Double {
let numberOfZeroes = Double(args.first?.value ?? 0)
let maximum = pow(10, numberOfZeroes)
return Double.random(in: 0...maximum)
}
}
let random = RandomNumberGenerator()
let result = random(numberOfZeroes: 0)
@dynamicCallable
struct RandomNumberGenerator {
func dynamicallyCall(withArguments args: [Int]) -> Double {
let numberOfZeroes = Double(args[0])
let maximum = pow(10, numberOfZeroes)
return Double.random(in: 0...maximum)
}
}
let random = RandomNumberGenerator()
let result = random(0)
func dynamicallyCallMethod(named: String, withKeywordArguments: KeyValuePairs<String, Int>)

V. Handling future enum cases

enum PasswordError: Error {
case short
case obvious
case simple
}
func showOld(error: PasswordError) {
switch error {
case .short:
print("Your password was too short.")
case .obvious:
print("Your password was too obvious.")
default:
print("Your password was too simple.")
}
}
func showNew(error: PasswordError) {
switch error {
case .short:
print("Your password was too short.")
case .obvious:
print("Your password was too obvious.")
@unknown default:
print("Your password wasn't suitable.")
}
}

V!. Flattening nested optionals resulting from try?

struct User {
var id: Int
init?(id: Int) {
if id < 1 {
return nil
}
self.id = id
}
func getMessages() throws -> String {
// complicated code here
return "No messages"
}
}
let user = User(id: 1)
let messages = try? user?.getMessages()

V!!. Checking for integer multiples

let rowNumber = 4if rowNumber.isMultiple(of: 2) {
print("Even")
} else {
print("Odd")
}

V!!!. Transforming and unwrapping dictionary values with compactMapValues()

let times = [
"Hudson": "38",
"Clarke": "42",
"Robinson": "35",
"Hartis": "DNF"
]
let finishers1 = times.compactMapValues { Int($0) }
let finishers2 = times.compactMapValues(Int.init)
let people = [
"Paul": 38,
"Sophie": 8,
"Charlotte": 5,
"William": nil
]
let knownAges = people.compactMapValues { $0 }

!X. Withdrawn: Counting matching items in a sequence

let scores = [100, 80, 85]
let passCount = scores.count { $0 >= 85 }
let pythons = ["Eric Idle", "Graham Chapman", "John Cleese", "Michael Palin", "Terry Gilliam", "Terry Jones"]
let terryCount = pythons.count { $0.hasPrefix("Terry") }

Native MacOS & iOS Engineer, Always ready to FLY