I need to handle an asynchronous task result. The problem is if I call it when it is in progress I need to update completion.
In GCD it will look somehow like that:
func someFunc(completion: (() -> ())?) {
if isLoading {
if let completion {
delayedCompletion = completion
}
return
}
isLoading = true
delayedCompletion = completion
//example of some async task
DispatchQueue.main.async { [weak self] in
self?.delayedContinuation?()
self?.delayedContinuation = nil
}
}
But how to do that with async/await? Tried to write code:
func someFunc() async {
if isLoading {
return await withCheckedContinuation { [weak self] checkedContinuation in
self?.delayedContinuation = checkedContinuation
}
}
isLoading = true
return await withCheckedContinuation { [weak self] checkedContinuation in
self?.delayedContinuation = checkedContinuation
Task { @MainActor [weak self] in
self?.delayedContinuation?.resume()
}
}
}
Is it correct or are there other ways to add a varying completion block?
There are a few basic patterns:
Await prior task.
Cancel prior task and launch a new one.
Having shown a couple of basic patterns, you likely want to fetch ads and present them in the UI, so you want to decouple the fetching from the presentation in the UI.
One might generate an asynchronous sequence of the ads from some “ad manager” and yield values as ads are fetched. So the UI can initiate the “periodically fetch ads” and then process them as they come in.
Then the UI can monitor this asynchronous sequence. E.g., in UIKit:
In SwiftUI, you don’t need this unstructured concurrency. Just directly
awaittheshowAdsfunction in a.taskview modifier, and it will start it when the view appears and will cancel it automatically when the view disappears. But, in UIKit, we need to manually handle cancelation, like above.Now, you haven’t shared your ad framework, so many of the details above may vary. But don’t get lost in the details. The basic idea in Swift concurrency is that you likely want an asynchronous sequence of ads, and then let the UI iterate through this sequence and present them as they come in. This is the natural Swift concurrency pattern for consuming an asynchronous sequence of events.