What’s New in Swift 5.7, WWDC 22
Great new features await us with Swift 5.7. Some are enhancements to Swift, while others are enhancements and improvements to make it easier for us to write code.
In this article, we will examine the innovations that come with Swift 5.7 with examples.
Clock, Instant and Duration
Swift announces the innovations it offers to make time and duration management more stable in the SE-0329 section.
Clock
Clocks represent a way of measuring time passing. There are two built in: the continuous clock keeps incrementing time even when the system is asleep, and the suspending clock does not.
SuspendedClock
- Measuring device time
- Delays for animations
ContinuesClock
- Measuring human time
- Delays by an absolute duration
// Measure elapsed duration of work
let clock = SuspendingClock()
let elapsed = await clock.measure {
await someLongRunningWork()
}
// Measure elapsed duration of work
let clock = ContinuousClock()
let elapsed = await clock.measure {
await someLongRunningWork()
}Instant
Instants represent an exact moment in time. Instants are there to be used to compare moments.
Duration
Duration can be used to represent the time elapsed between two Instant.
New “if-let” Unwrapping Syntax
With Swift 5.7, you will now be able to unwrap an optional value in a shorter way. This was announced in section SE-0345.
// Swift 5.6 and prior
let appCircle: AppCircle?
if let unwrappedAppCircle = appCircle {
// `appCircle` is of type `AppCircle`
}
// Swift 5.7
let appCircle: AppCircle?
if let appCircle {
// `appCircle` is of type `AppCircle`
}Multi-statement closure parameter/result type inference
We no longer have to define result types when we use the closures we love to use. Swift will handle this for us. See SE-0326.
As you know before, we had to define these result types and the code we wrote was increasing.
let points = [25, 47, 12, 78, 90]
let results = points.map { point in
if point >= 70 {
return "\(point): Well done!"
}
return "\(point): Nice try! :("
}
/* Old way
let points = [25, 47, 12, 78, 90]
let result = points.map { point -> String in
if point >= 70 {
return "\(point): Well done!"
}
return "\(point): Nice try! :("
}
*/Opaque Parameter Declarations
If you’ve ever been interested in SwiftUI, you’ve probably heard of the ‘some’ keyword. When we put this keyword in front of a parameter, the parameter becomes Opaque.
Well, if you say what will be the use of these Opaque type parameters, our code will be more readable and reduced when using Swift Generics with Opaque types. Additionally, we can use the ‘any’ keyword.
- Holds a fixed concrete type
- Guarantees type relationship
Any
- Holds an arbitrary concrete type
- Erases type relationships
// `some`
protocol Animal {
associatedtype Feed: AnimalFeed
func eat(_ food: Feed)
}
struct Farm {
func feed(_ animal: some Animal) {
let crop = type(of: animal).Feed.grow()
}
}
// `any`
let technologies: [any Equatable] = ["AppCircle", 10]Regex
Regex operations are now easier with Swift 5.7. Prior to this we had to deal with Range and NSRegularExpression.
Now, thanks to Regex type, we will be able to do the regular expression operations we need more easily.
See SE-0350.
Regexes can be created at run time from a string containing familiar regex syntax. If no output type signature is specified, the regex has type Regex<AnyRegexOutput>, in which captures are existentials and the number of captures is queryable at run time. Alternatively, providing an output type signature produces strongly-typed outputs, where captures are concrete types embedded in a tuple, providing safety and enabling source tools such as code completion.
let pattern = #"(\w+)\s\s+(\S+)\s\s+((?:(?!\s\s).)*)\s\s+(.*)"#
let regex = try! Regex(pattern)
// regex: Regex<AnyRegexOutput>
let regex: Regex<(Substring, Substring, Substring, Substring, Substring)> =
try! Regex(pattern)By examining the code block below, you can better understand how we use the new regex type with a comparative example.
let text = "AppCircle is a great tool for CI/CD pipeline management."
// Old
print(text.ranges(of: "for"))
print(text.replacing("great", with: "excellent"))
// New
print(text.ranges(of: /[a-z]for/))
print(text.replacing(/[a-z]at/, with: "excellent"))
