Swift 5.3, which has recently become available with Xcode 12, includes a number of significant new features at the syntax level, including support for multi-pattern catch
clauses, increased availability for implicit self
, and more. Additionally, the Swift team has worked on improving runtime performance, especially when using SwiftUI, and developer experience.
Swift 5.3 makes error handling with do try/catch
more convenient by allowing to specify more patterns with a single catch
clause. For example, you can now write:
do {
try performTask()
} catch TaskError.someRecoverableError {
recover()
} catch TaskError.someFailure(let msg),
TaskError.anotherFailure(let msg) {
showMessage(msg)
}
Another features meant to make the language more natural to use is enum
types being able now to synthesize conformance to Comparable
. This means you can now use any comparison operators with enums
to compare their values according to the declaration order of their cases
. For example, you can write:
enum Membership : Comparable {
case premium(Int) // <
case preferred // <
case general
}
let planA = Membership.premium
let planB = Membership.general
if planA < planB {
...
}
[ .general, .premium, .preferred ].sorted()
In Swift 5.3, implicit self
can be used in places where it could not be earlier, such as escaping closures when no risk of creating reference cycles exists. This includes specifically the case where self
is a value type. Indeed, when self
is a reference to a value type, such as a struct
, no reference cycle can ensue, so we can safely write:
struct Test {
var x = 0
func execute(_ work: @escaping () -> Void) {
work()
}
func method() {
execute {
x += 1 // instead of: self.x
}
}
}
Similarly, this rule applies also to cases where the user has made their intention clear, such as when specifying self
in the closure capture list, as in the following class
-based version of the above snippet:
class Test {
var x = 0
func execute(_ work: @escaping () -> Void) {
work()
}
func method() {
execute { [self] in
x += 1 // instead of: self.x
}
}
}
Besides these and and many other syntax changes, Swift 5.3 also improves binary code size and runtime memory usage. Based on Apple measurements, this could lead to a 30%-40% reduction in code size and 60% reduction in heap size. Of course, these results depend strongly on the specific code considered and its patterns of use, so your mileage may vary here. Significantly, though, according to Apple, an application written in Swift should now use less heap memory than the equivalent Objective-C code.
On the front of developer experience, Swift 5.3 brings better indentation, specifically with chained method class involving closures; with function arguments, parameters, and collection elements that span multiple lines; and with multi-line if
, guard
and while
conditions. In addition, code completion has become faster when repeatedly using the same symbol from inside a function.
Swift 5.3 should also be faster at incremental compilation by avoiding duplicated work across files and by better identifying unchanged code. In general, the Swift compiler is now faster with types using large number of properties and functions imported from another library and should be less dependent on declaration order or nesting.
As a final note about tooling, Swift 5.3 improves diagnostics in a number of cases, especially with SwiftUI code.
The number of changes in Swift 5.3 goes well beyond the limits of what can be covered here, so do not miss the official release announcement for the full details.