This is a living article that outlines what changes have been merged ready for the release of Swift 5.6 you can keep monitoring this here on the Github readme file.
Allow Coding of Dictionaries [SE-0320]
It’s always been a limitation in that encoding can only be done on String/Int types and if you wanted to code a Dictionary then a workaround was always required. Well, thanks to this proposal it makes it much simpler.
This proposal introduces a whole new protocol named CodingKeyRepresentable
.
Types conforming to CodingKeyRepresentable
indicate that they can be represented by a CodingKey
instance, allowing them to opt into having dictionaries use their CodingKey
representations in order to encode into KeyedContainer
s.
// Same as stdlib's _DictionaryCodingKey
struct _AnyCodingKey: CodingKey {
let stringValue: String
let intValue: Int?
init(stringValue: String) {
self.stringValue = stringValue
self.intValue = Int(stringValue)
}
init(intValue: Int) {
self.stringValue = "\(intValue)"
self.intValue = intValue
}
}
struct ID: Hashable {
static let registrationId = ID(stringValue: "my_id")
let stringValue: String
var codingKey: CodingKey {
return _AnyCodingKey(stringValue: stringValue)
}
init?<T: CodingKey>(codingKey: T) {
stringValue = codingKey.stringValue
}
init(stringValue: String) {
self.stringValue = stringValue
}
}
let data: [ID: String] = [
.registrationId: "result"
]
let encoder = JSONEncoder()
try String(data: encoder.encode(data), encoding: .utf8)
Introducing CodingKeyRepresentable conformance would allow the above to work as previously would fail. This example was taken directly from the proposal because its really nice example usage.
Supported Concurrency Migration [SE-0337]
Swift 5.5 introduced all-new ways to prevent data races, including the introduction of the Sendable
protocol. Sendable
is a way to mark values that can be used across different actors and prevent data from colliding.
However, Swift 5.5 doesn’t enforce the use of Sendable
and is optional, which means data races can happen.
Therefore, this proposal means by default the compiler will check for these possible data races that could happen. For example:
@MainActor func doSomethingThenFollowUp(_ body: @Sendable () -> Void) {
// do something
Task.detached {
// do something else
body()
}
}
In the above example, you’re potentially changing data which could result in a data race. So in this proposal, the compiler will check for these possibilities.
So, by default, the above example will throw compiler errors for accessing data outside the MainActor
.
Within the scope of this proposal we have a new introduction:
@preconcurrency import AdamsBankModule
This new @preconcurrency
allows you to define that this module or code is yet to abide by the implementation and therefore will silence any errors. It also means that folk who are maintaining an SDK can mark something as migrating to all new concurrency in Swift.
Inverted Availability Condition Checking [SE-0290]
Take this example, it’s going to be so much easier to write inverted availability code soon with the introduction of #unavailable()
It was actually very common to use empty implementations when using #available()
so this is super useful to provide the opposite for available conditions.
if #unavailable(iOS 15.0) {
// Some code
}
Type Expressions Now Include Type Placeholders [SE-0315]
Type expressions and annotations can now include “type placeholders” which directs the compiler to fill in that portion of the type according to the usual type inference rules. Type placeholders are spelt as an underscore (“_
“) in a type name.
// This is OK, the compiler can infer the value type as `Int`.
let dict: [Int: _] = [0: 10, 1: 20, 2: 30]
The Road to Swift 6.0?
We’re certainly getting closer to the next major version of Swift, could it be coming this year during WWDC? We’ll see for sure and it’s probably a great excuse for Apple to introduce some breaking changes, either way, let’s see what will come.