Swift’s latest major release contains many changes and updates to the language and the standard library, most notably new String
features, extended collections, archival and serialization, and more.
In Swift 4 strings conform to the Collection
protocol, which makes them directly iterable and provides all the facilities you are used to with collection and sequences, for example:
for c in myString {
print(c)
}
myString.filter { c in
return boolCheck(c)
}
let l = myString.count
let myString2 = myString.dropFirst()
Additionally, string slices are now instances of type Substring
, which conforms to StringProtocol
and can thus be used identically to type String
. This change helps improve performance of slicing, since a Substring
will not copy the string slice. The copy operation can be deferred to the time the Substring
is converted into a String
to be consumed by some API.
Other new string features are support for Unicode 9 and multi-line literals.
Swift 4 also improves the way you can create, use, and manage collection types, such as Dictionary
and Set
.
First of all, you can now create a dictionary from a sequence of tuples as well as specify how you handle duplicates, if any, both when creating a dictionary or merging two dictionaries:
let items = ["ItemA", "ItemB", "ItemC", "ItemA"]
let prices = [14.40, 41.63, 3.71, 15.63]
let catalog1 = Dictionary(uniqueKeysWithValues: zip(items, prices))
let catalog2 = Dictionary(prices, uniquingKeysWith: { (l, r) in
l })
let catalog3 = Dictionary(prices, uniquingKeysWith: { (l, r) in
l + r })
let merged = catalog.merge(catalog3) { (l, r) in r }
Dictionary
and Set
now can be filtered into another object of the original type, instead of into an Array
. Furthermore, dictionaries support a new mapValues
method:
let catalog4 = catalog.filter { $0.value < 15.0 }
let catalog5 = catalog.mapValues { $0 * 1.2 }
Another useful addition to dictionaries is the possibility of specifying a default value when accessing its elements, which makes the subscript operator return a non-opt type:
let price1 : Float = catalog['none', default: 0.0]
let price2 : Float? = catalog['none']
All Collection
types support generic subscripts in Swift 4. This means you could define the following JSON
struct and not cast the result of indexing into the dictionary:
struct JSON {
init(dictionary: [String:Any]) {
...
}
subscript<T>(key: String) -> T? {
...
}
}
let json = ...
let result: String? = json['item']
Another welcome enhancement to the language is support for archival and serialization, which previously required dealing with NSObject
and NSCoding
, which was not an option for struct
and enum
types. Instead, Swift 4 adds serialization to all types through the Codable
protocol. Ole Begemann provided a nice introduction to coding and decoding in Swift 4. For example, this is how you can define a Codable
type:
struct Card: Codable, Equatable {
enum Suit: String, Codable {
case clubs, spades, hearts, diamonds
}
enum Rank: Int, Codable {
case two = 2, three, four, five, six, seven, eight, nine, ten, jack, queen, king, ace
}
var suit: Suit
var rank: Rank
static func ==(lhs: Card, rhs: Card) -> Bool {
return lhs.suit == rhs.suit && lhs.rank == rhs.rank
}
}
let hand = [Card(suit: .clubs, rank: .ace), Card(suit: .hearts, rank: .queen)]
As a last note, Swift 4 has two language modes, selected through the -swift-version
compiler option. In Swift 3.2 mode, the compiler will accept the majority of sources compatible with Swift 3.x compilers. In this mode, most Swift 4 language features will be available, but updates to previously existing APIs will not. In Swift 4.0 mode, you will get access to all Swift 4 features, at the expense of some source changes, which as usual can be handled using Xcode’s migration assistant.
There is much more to Swift 4. Do not miss Swift maintainer Ted Kremenek announcement and Ole Begemann’s interactive Playground demoing all new features.
Swift 4 is included in Xcode 9 and can be manually installed in Xcode 8.3.