Printed on: April 24, 2022
Once 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 may name with the results of your asynchronous work. You may have the choice to move it the output of your work, an object that conforms to Error
, or you’ll be able to move it a Outcome
.
On this submit, I received’t go in-depth on exhibiting you the right way to convert your callback based mostly code to async/await (you’ll be able to seek advice from this submit in the event you’re involved in studying extra). As a substitute, I’d like to clarify the distinction between a checked and unsafe continuation on this brief submit.
For those who’ve labored with continuations earlier than, you will have seen that there are 4 strategies that you need to use to create a continuation:
withCheckedThrowingContinuation
withCheckedContinuation
withUnsafeThrowingContinuation
withUnsafeContinuation
The principle 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 let you know 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 right, 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 may name with the end result of a conventional 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 (Outcome<Token, Error>) -> Void) {
// finally calls the completion closure
}
func validTokenFromCompletion() async throws -> Token {
return attempt await withCheckedThrowingContinuation { continuation in
validToken { lead to
continuation.resume(with: outcome)
}
}
}
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 bear in mind:
- It is best 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 price. In different phrases, your code will probably beawait
-ing ceaselessly.
For those who fail to do both of the 2 factors above, that’s a developer mistake and you must 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 let you know what’s unsuitable.
In fact, there’s some overhead in performing these checks (though this overhead isn’t huge). To eliminate this overhead, we will make use of an unsafe continuation.
Is it vital that you simply eliminate this overhead? No, in by far essentially the most conditions I extremely doubt that the overhead of checked continuations is noticeable in your apps. That stated, in the event you do discover a purpose to eliminate your checked continuation in favor of an unsafe one, it’s vital that you simply perceive what an unsafe continuation does precisely.
Understanding what an unsafe continuation does
Briefly, an unsafe continuation works in the very same approach as a checked one, with the identical guidelines, besides it doesn’t verify that you simply adhere to the foundations. Which means errors is not going to be caught early, and also you received’t get a transparent description of what’s unsuitable in your crash log.
As a substitute, an unsafe closure simply runs and it’d crash or carry out different undefined conduct while you break the foundations.
That’s actually all there’s 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 workforce recommends that we at all times make use of checked continuations throughout growth, a minimum of till we’ve verified the correctness of our implementation. As soon as we all know our code is right and our checked continuation doesn’t throw up any warnings at runtime, it’s protected (sufficient) to modify to an unsafe continuation in the event you’d like.
Personally, I choose to make use of checked continuations even once I know my implementation is right. This enables me to proceed engaged on my code, and to make modifications, with out having to recollect to modify forwards and backwards between checked and unsafe continuations.
In fact, there’s some overhead concerned with checked continuations and in the event you really feel such as you may profit from utilizing an unsafe continuation, you must at all times profile this primary and make it possible for this swap is definitely offering you with a efficiency profit. Making your code much less protected based mostly on assumptions isn’t an awesome concept. Personally, I’ve but to discover a purpose to favor an unsafe continuation over a checked one.