Open utterances-bot opened 3 years ago
This is a GREAT article. Thanks for the write up.
I am baffled sometimes when implementing this on occasion. Sometimes if just works, and other times I get an error.
Here's an example of when it doesn't work:
func getAppleMusicUserToken() async throws -> String {
return try await withCheckedThrowingContinuation ({ (continuation: CheckedContinuation<String, Error>) in
do {
let tokenProvider = DefaultMusicTokenProvider()
let options = MusicTokenRequestOptions()
let devToken = try await tokenProvider.developerToken(options: options)
let userToken = try await tokenProvider.userToken(for: devToken, options: options)
continuation.resume(returning: userToken)
} catch {
print(error)
continuation.resume(throwing: error)
}
})
}
The error is:
Cannot pass function of type '(CheckedContinuation<String, Error>) async -> Void' to parameter expecting synchronous function type
I know I'm doing something, dumb, but I just don't know what it is!
Any tips?
Dumb follow up: Why not just do this, or am I missing the point?
func getAppleMusicUserToken() async throws -> String {
do {
let tokenProvider = DefaultMusicTokenProvider()
let options = MusicTokenRequestOptions()
let devToken = try await tokenProvider.developerToken(options: options)
print("devToken \(devToken)")
let userToken = try await tokenProvider.userToken(for: devToken, options: options)
print("userToken \(userToken)")
return userToken
} catch {
print(error)
throw error
}
}
@kimfucious The example with the new Apple Music framework is not a good example because it is already async/await. Checked continuations help you migrate non async await code into async await code. You won't find many of these within Apple's SDKs, but very likely in third party libraries.
I knew I was being dumb, thanks!
Is it possible to use async/await
in iOS version earlier than iOS 15?
Hey, I can't find any examples how to transform functions that have @espaping closure with empty parentheses. These functions usually do something and then call completion. If I make it async, it would return Void. And another problem is I tried to use continuations, like Apple gave an example in AsyncSequence WWDC video. But I use optional handlers as properties, and in my VC I create a class that contains those properties lazily and initialize handlers inside this block. Like this:
class Manager {
var handler: (() -> Void)?
func doSomething() {
doSomethingElse()
handler?()
}
func doSomethingElse() {
...
}
}
class ViewController: UIVIewController {
lazy var manager = {
let manager = Manager()
manager.handler = {
doSomerhing()
}
return manager
}()
}
@alexryakhin if you are talking about callbacks that are called after something is done executing, wouldn't you just put the code underneath the async call in the async/await version?
class Manager {
var handler: (() -> Void)? // you would get rid of this
func doSomething() async {
doSomethingElse()
//handler?()
}
func doSomethingElse() {
...
}
}
let myManager = Manager()
await myManager.doSomething()
// Write the code you'd put inside the handler here...
Unless of course I'm misunderstanding something in your question.
in chooseContactTouchUpInside you did just async block: async {...} I haven't seen such construction in previous articles. Can u pls give some explanation of it?
in chooseContactTouchUpInside you did just async block: async {...} I haven't seen such construction in previous articles. Can u pls give some explanation of it?
Thanks for pointing that out. It should be Task { ... }
instead of async {...}
. Earlier betas used the async {}
construct instead of Task
.
Great article Andy, saved me a lot of time. 👏🏻
Converting closure-based code into async/await in Swift • Andy Ibanez
https://www.andyibanez.com/posts/converting-closure-based-code-into-async-await-in-swift/