How do I use the new Swift 5.5 await
keyword to wait for a duration of time?
Normally, with completion handlers, you would have something like this by using DispatchQueue
's asyncAfter(deadline:execute:)
:
func someLongTask(completion: @escaping (Int) -> Void) {
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
completion(Int.random(in: 1 ... 6))
}
}
someLongTask { diceRoll in
print(diceRoll)
}
How can this be converted to using async
& await
in Swift 5.5?
There's a newer API, sleep(for:tolerance:clock:)
, used like so:
// 3 seconds
try await Task.sleep(for: .seconds(3))
You can use Task.sleep(nanoseconds:)
to wait for a specific duration. This is measured in nanoseconds, not seconds.
Here's an example:
func someLongTask() async -> Int {
try? await Task.sleep(nanoseconds: 1 * 1_000_000_000) // 1 second
return Int.random(in: 1 ... 6)
}
Task {
let diceRoll = await someLongTask()
print(diceRoll)
}
It may be easier to use an extension for sleep so you can just pass in seconds:
extension Task where Success == Never, Failure == Never {
static func sleep(seconds: Double) async throws {
let duration = UInt64(seconds * 1_000_000_000)
try await Task.sleep(nanoseconds: duration)
}
}
Which would now be called like so:
try await Task.sleep(seconds: 1)
Note that sleep is called with try
. An error is thrown if the sleep is cancelled. If you don’t care if it’s cancelled, just try?
is fine.