SE-0374 adds a new extension method to Swift’s Clock
protocol that allows us to suspend execution for a set number of seconds, but also extends duration-based Task
sleeping to support a specific tolerance.
The Clock
change is a small but important one, particularly if you’re mocking a concrete Clock
instance to remove delays in tests that would otherwise exist in production.
For example, this class can be created with any kind of Clock
, and will sleep using that clock before triggering a save operation:
class DataController: ObservableObject {
var clock: any Clock<Duration>
init(clock: any Clock<Duration>) {
self.clock = clock
}
func delayedSave() async throws {
try await clock.sleep(for: .seconds(1))
print("Saving…")
}
}
Because that uses any Clock<Duration>
, it’s now possible to use something like ContinuousClock
in production but your own DummyClock
in testing, where you ignore all sleep()
commands to keep your tests running quickly.
In older versions of Swift the equivalent code would in theory have been try await clock.sleep(until: clock.now.advanced(by: .seconds(1)))
, but that wouldn’t work in this example because clock.now
isn’t available as Swift doesn’t know exactly what kind of clock has been used.
As for the change to Task
sleeping, it means we can go from code like this:
try await Task.sleep(until: .now + .seconds(1), tolerance: .seconds(0.5))
To just this:
try await Task.sleep(for: .seconds(1), tolerance: .seconds(0.5))
SAVE 50% To celebrate Black Friday, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.
Sponsor Hacking with Swift and reach the world's largest Swift community!
Download all Swift 5.9 changes as a playground Link to Swift 5.9 changes
Link copied to your pasteboard.