I have an app that does some processing given a string, this is done in 2 Task
s. During this time i'm displaying an animation. When these Task
s complete i need to hide the animation. The below code works, but is not very nice to look at. I believe there is a better way to do this?
let firTask = Task {
/* Slow-running code */
}
let airportTask = Task {
/* Even more slow-running code */
}
Task {
_ = await firTask.result
_ = await airportTask.result
self.isVerifyingRoute = false
}
Isn't the real problem that this is a misuse of Task? A Task, as you've discovered, is not really of itself a thing you can await. If the goal is to run slow code in the background, use an actor. Then you can cleanly call an actor method with await.
let myActor = MyActor()
await myActor.doFirStuff()
await myActor.doAirportStuff()
self.isVerifyingRoute = false
However, we also need to make sure we're on the main thread when we talk to self
— something that your code omits to do. Here's an example:
actor MyActor {
func doFirStuff() async {
print("starting", #function)
await Task.sleep(2 * 1_000_000_000)
print("finished", #function)
}
func doAirportStuff() async {
print("starting", #function)
await Task.sleep(2 * 1_000_000_000)
print("finished", #function)
}
}
func test() {
let myActor = MyActor()
Task {
await myActor.doFirStuff()
await myActor.doAirportStuff()
Task { @MainActor in
self.isVerifyingRoute = false
}
}
}
Everything happens in the right mode: the time-consuming stuff happens on background threads, and the call to self
happens on the main thread. A cleaner-looking way to take care of the main thread call, in my opinion, would be to have a @MainActor
method:
func test() {
let myActor = MyActor()
Task {
await myActor.doFirStuff()
await myActor.doAirportStuff()
self.finish()
}
}
@MainActor func finish() {
self.isVerifyingRoute = false
}
I regard that as elegant and clear.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With