Swift 4.1, available in Xcode 9.3, brings a number of improvements to the language, including automatic implementation of the Equatable
and Hashable
protocols, conditional conformance, and more.
Conditional conformance
Conditional conformance allows the expression of the idea that a generic type will conform to a protocol only if its type parameters satisfy certain requirements. For example an Array
can implement the Equatable
protocol only if its elements also conform to it, which can be expressed in the following declaration:
extension Array: Equatable where Element: Equatable {
static func ==(lhs: Array<Element>, rhs: Array<Element>) -> Bool { ... }
}
This closes a gap in Swift generics, fully enabling the possibility of generic adapter types, i.e., generic types that reflect the capabilities of the composing types. For example, in Swift 3 there exist four different generic types that handle "lazy" items: LazySequence
, LazyCollection
, LazyBidirectionalCollection
, and LazyRandomAccessCollection
. Each of those types reimplements, or forwards, the same API as the composing type. Using conditional conformance, a Sequence
of a lazy type can be declared as conforming to the lazy protocol without defining any intermediate generic types.
Synthesized ==
and hashValue
The Swift 4.1 compiler is able to synthesize the implementation of the ==
and hashValue
methods for structs and enums that declare conformance to the Equatable
and Hashable
protocols. Previously, developers had to provide a custom implementation of those methods, which was a rather tedious task: the ==
method implementation had, in the general case, to compare each corresponding member of the structs or unions, while the hashValue
had to somehow ensure that it returned a unique string. In Swift 4.1, developers can just declare conformance to those protocols and the relevant methods will be automatically synthesized, provided all stored properties or enum cases conform to Equatable
or Hashable
respectively.
Other significant changes in Swift 4.1 are the following:
-
Index types for most library collections conform now to
Hashable
and can be used in key-path subscripts and hashed collections:let s = "Hashable" let p = \String.[s.startIndex] s[keyPath: p] // "H"
-
Smart KeyPaths are fully implemented. KeyPaths now support subscript, optional chaining, and optional force-unwrapping.
- Keywords
weak
andunowned
cannot be used anymore for property declaration in protocols. - Similarly to a restriction already existing for classes, Swift structs no longer allow defining an initializer in a different module that directly initialized the struct’s fields. Before accessing struct fields, the struct must have been initialized calling
self.init
.
A full list of all changes within Swift 4.1 can be found in the official change log.