Revealed on: April 24, 2022
While you’re writing a conversion layer to remodel your callback based mostly code into code that helps async/await in Swift, you’ll usually end up utilizing continuations. A continuation is a closure that you would be able to name with the results of your asynchronous work. You may have the choice to go it the output of your work, an object that conforms to Error
, or you possibly can go it a End result
.
On this submit, I received’t go in-depth on displaying you the best way to convert your callback based mostly code to async/await (you possibly can confer with this submit for those who’re all in favour of studying extra). As a substitute, I’d like to elucidate the distinction between a checked and unsafe continuation on this brief submit.
Should you’ve labored with continuations earlier than, you will have observed that there are 4 strategies that you should utilize to create a continuation:
withCheckedThrowingContinuation
withCheckedContinuation
withUnsafeThrowingContinuation
withUnsafeContinuation
The primary factor that ought to stand out right here is that you’ve got the choice of making a “checked” continuation or an “unsafe” continuation. Your intestine may inform you to at all times use the checked model as a result of the unsafe one sounds… properly… unsafe.
To determine whether or not that is appropriate, let’s check out what we get with a checked continuation first.
Understanding what a checked continuation does
A checked continuation in Swift is a continuation closure that you would be able to name with the result of a standard asynchronous operate that doesn’t but use async/await, usually one with a callback closure.
This may look a bit as follows:
func validToken(_ completion: @escaping (End result<Token, Error>) -> Void) {
// finally calls the completion closure
}
func validTokenFromCompletion() async throws -> Token {
return strive await withCheckedThrowingContinuation { continuation in
validToken { end in
continuation.resume(with: end result)
}
}
}
The code above is a quite simple instance of bridging the normal validToken
methodology into the async/await world with a continuation.
There are a few guidelines for utilizing a continuation that you simply want to remember:
- You need to solely name the continuation’s
resume
as soon as. No extra, no much less. Calling theresume
operate twice is a developer error and might result in undefined conduct. - You’re accountable for retaining the
continuation
and callingresume
on it to proceed your code. Not resuming yourcontinuation
implies thatwithCheckedThrowingContinuation
won’t ever throw an error or return a worth. In different phrases, your code might beawait
-ing endlessly.
Should you fail to do both of the 2 factors above, that’s a developer mistake and it is best to repair that. Fortunately, a checked continuation performs some checks to make sure that:
- You solely name
resume
as soon as - The
continuation
handed to you is retained in your closure
If both of those checks fail, your app will crash with a descriptive error message to inform you what’s improper.
After all, there’s some overhead in performing these checks (though this overhead isn’t monumental). To do away with this overhead, we will make use of an unsafe continuation.
Is it necessary that you simply do away with this overhead? No, in by far probably the most conditions I extremely doubt that the overhead of checked continuations is noticeable in your apps. That mentioned, for those who do discover a purpose to do away with your checked continuation in favor of an unsafe one, it’s necessary that you simply perceive what an unsafe continuation does precisely.
Understanding what an unsafe continuation does
In brief, an unsafe continuation works in the very same means as a checked one, with the identical guidelines, besides it doesn’t test that you simply adhere to the foundations. Because of this errors won’t be caught early, and also you received’t get a transparent description of what’s improper in your crash log.
As a substitute, an unsafe closure simply runs and it would crash or carry out different undefined conduct if you break the foundations.
That’s actually all there may be to it for an unsafe continuation, it doesn’t add any performance, it merely removes all correctness checks {that a} checked continuation does.
Selecting between a checked and an unsafe continuation
The Swift crew recommends that we at all times make use of checked continuations throughout growth, not less than till we’ve verified the correctness of our implementation. As soon as we all know our code is appropriate and our checked continuation doesn’t throw up any warnings at runtime, it’s protected (sufficient) to modify to an unsafe continuation for those who’d like.
Personally, I favor to make use of checked continuations even once I know my implementation is appropriate. This enables me to proceed engaged on my code, and to make adjustments, with out having to recollect to modify backwards and forwards between checked and unsafe continuations.
After all, there may be some overhead concerned with checked continuations and for those who really feel such as you may profit from utilizing an unsafe continuation, it is best to at all times profile this primary and ensure that this change is definitely offering you with a efficiency profit. Making your code much less protected based mostly on assumptions is rarely an awesome concept. Personally, I’ve but to discover a purpose to favor an unsafe continuation over a checked one.