The latest release of Apple's language, Swift 5.5, introduces new features aimed at making it easier for developers to write asynchronous code as well as several extensions to the language and compiler, not the least CGFloat
and Double
interchangeability.
The new concurrency features, which include async/await
, asynchronous sequences, and actors, radically change how developers write asynchronous code, bringing it closer to languages such as C#, F#, JavaScript/TypeScript, and many others.
InfoQ timely covered Swift 5.5 new concurrency features at the moment of their announcement at WWDC 2021. As a short refresher, functions can now opt into being async
, which will make the compiler translate them into code using futures and promises. The main advantage from a programmer standpoint is that async/await
makes it possible to structure concurrent code under the disguise of sequential code. Actors, on the other hand, allow developers to encapsulate state behind an operation queue that will sequentialize write access to it. We refer readers to our former coverage for additional detail.
As mentioned, this Swift release does not only focus on concurrency. A new feature that will be particularly welcome by most developers is the possibility of using CGFloat
and Double
types interchangeably. For example:
let cgFloat: CGFloat = 42
let double: Double = 19
let mix = cgFloat + double
Under the hood, the Swift compiler will bridge all CGFloat
s to Double
s, which means all existing APIs are left unchanged. It must be noted that this bridging has some limitations in the current implementation. In particular, while Double
can be used where a CGFloat?
is required and a CGFloat
can be passed as a Double?
, no bridging is allowed between Double?
and CGFloat?
, for which case you will need to explicitly cast types. Similarly, bridging does not work within tuples.
Swift 5.5 also upgrades enum
types with associated values so they can be auto-synthesized when conforming to the Codable
protocol. Previously, enum
with associated values could only be auto-synthesized when conforming to the RawRepresentable
protocol, forcing the developer to write some boilerplate for other cases. For example, you can now declare:
enum Command: Codable {
case load(key: String)
case store(key: String, value: Int)
}
which will be encoded to:
{
"load": {
"key": "MyKey"
}
}
{
"store": {
"key": "MyKey",
"value": 42
}
}
Property wrappers, which were introduced in Swift 5.1, have been extended in Swift 5.5 so you apply them to function and closure parameters. In brief, property wrappers are a mechanism that allows programmers to define some recurrent pattern and assign it a name so it can be reused easily. For example, the Swift language includes support for the lazy
and @NSCopying
keywords, that specify a concrete behaviour for the properties they are attached to. Property wrappers can be seen as a generalization of this mechanism that is open for developers to create new patterns according to their needs. In Swift 5.1 you could for example declare a property wrapper Field
that references a database field by name with the ability to read/write its associated value transparently:
@propertyWrapper
public struct Field<Value: DatabaseValue> {
...
}
Once defined, you could use the property wrapper to decorate some properties:
public struct Person: DatabaseModel {
@Field(name: "first_name") public var firstName: String
...
}
New in Swift 5.5, you can use property wrappers as parameters to functions and closures, which was not previously allowed.
Swift 5.5 includes many more features than what can be summarized here, including package collections, static member lookup extension in generics, task local control, and more. Do not miss the official announcement for pointers to the corresponding Swift Evolution proposals.
Swift 5.5 is currently available as part of Xcode 13 as well as for Linux and Windows 10.