On September 19, 2017, Apple announced release of Swift 4.0 on the official blog of Swift language. Great news is that new Swift doesn’t contain so many epic changes like Swift 3.0 did, and most changes have full backwards compatibility. So you can just relax and kick back, let’s take a quick look at all innovations.

1. One-Sided Ranges

RangeExpression protocol was added to simplify creation of methods that use ranges. Also the standard library can detect start and end indices of ranges from now, so you don’t need to explicitly specify them [SE-0172]:

let s = "Hello, World!"



let i = s.index(of: ",")! // half-open right-handed range



let greeting = s[..<i]



// closed right-handed range



let withComma = s[...i]



// left-handed range (no need for half-open variant)



let location = s[i...]]

A great way to use one-sided ranges is pattern matching:

switch year {



case 2001...: print("Next millennium is here")



default: print("Keep calm and wait!")



}

2. Strings and chars updates

Multi-line String Literals

The multi-line string literals come in handy when you need to build long formatted texts for UI or XML or JSON messages. In Swift 4, you can do this using three double-quotes (""") [SE-0168]:

let longAndFormatedString = """



“Talk is cheap. Show me the code.”



― Linus Torvalds



""" “Talk is cheap. Show me the code.”



― Linus Torvalds

You don't have to avoid quotes in here, very useful.

String Newline Escaping

Another capability that was added in Swift 4.0 is simple, but helpful - preventing line breaking by adding (\) [SE-0182]

let escapeNewLine = """



“Talk is cheap. Show me the code.” \



― Linus Torvalds



""" “Talk is cheap. Show me the code.” ― Linus Torvalds

String is a Collection... again

Strings are collections like they were before Swift 2.0. This change allows us to skip characters array usage during iteration, you can do it directly over String.

let iterateMe = "Please"







for char in iterateMe {



print(char)



}

String, Substring, and StringProtocol

To improve operation of string slices, they become instances of Substring and conform to new protocol StringProtocol as well as String.

let ordinaryString = "I am full string"



let endIndex = ordinaryString.index(ordinaryString.startIndex, offsetBy: 6)



let substring = ordinaryString[...endIndex]



type(of: substring) // Substring

Developers need to keep in mind that a Substring keeps the full String value it was created from alive. This can lead to incorrect memory usage. To prevent such situations, it is recommended that most functions, which take strings as arguments, continue accepting only String instances.

You generally should not make such functions generic to accept any value conforming to StringProtocol. To convert Substring into String, use String initializer:

let newString = String(substring)

Unicode 9

Swift 3 doesn’t determine the number of unicode characters made up of multiple code points correctly. This issue is fixed in Swift 4.

" ".count // person + skin tone; in Swift 3: 2 " ".count // person + skin tone + profession; in Swift 3: 3 " ".count // multiple flags; in Swift 3: 1

The unicodeScalars Property Added to Character

Swift 4 adds the unicodeScalars property to characters, so you can access it directly now [SE-0178]:

let character: Character = "A" let unicodeScalars = character.unicodeScalars

3. Private Access Modifier for extensions

Swift 4 realizes the original intent by sharing the same access control scope between a type and any extension of said type. This only holds true within the same source file [SE-0169]:

struct StructWithPrivateFoo {



private var foo: Int = 0



} extension StructWithPrivateFoo {



mutating func modifyFooWith(i: Int) {



// foo is visible here



foo = i



}



}

4. Smart KeyPaths

Unlike the string-based key paths in Cocoa, Swift key paths are strongly typed. Now to create a key path, you simply use a back-slash followed by the property you're interested in:

struct User {



let name: String



} let user = User(name: "Vasil") let keyPath = \User.name



let userName = user[keyPath: keyPath]

Key paths are objects that can be stored and manipulated.

5. Encoding & Decoding

Archival and Serialization

Earlier, to serialize and archive your custom types, you had to do extra work: for classes you had to subclass NSObject and implement the NSCoding protocol, for value types you had to do even more work. In Swift 4, this problem is solved by adding the Codable protocol [SE-0166]:

struct Video: Codable {



enum Kind: Int, Codable {



case Unknown, Static, Live



} let kind: Kind







let isPlaying: Bool



let isBuffering: Bool



} let video = Video(kind: .Static, isPlaying: true, isBuffering: false)

Encoding

Once you have a Codable value, you need to pass it to an encoder in order to archive it. Swift 4 comes with a built-in set of encoders and decoders for JSON (JSONEncoder and JSONDecoder) and property lists (PropertyListEncoder and PropertyListDecoder). These are defined in [SE-0167]:

var encoder = JSONEncoder()



let jsonData = try encoder.encode(video)



let jsonString = String(data: jsonData, encoding: .utf8)



// {"kind":1,"isBuffering":false,"isPlaying":true}

Decoding

Decoding is pretty similar:

let decoder = JSONDecoder()



let decodedVideo = try decoder.decode([Video].self, from: jsonData)

There are more changes presented by Swift 4, including updates to Dictionary and Set, improved integers, generic subscripts, and more. Read about about them in Swift 4, Review the New - Part Two. Stay tuned!