Pursuing async/await
Finally async/await is going to appear in Swift5.5 and plenty of videos on WWDC2021 contains explanations how to use those “words” for asynchronous, concurrent programming…
In a nutshell our typical long constructs, such as nested dispatch calls could be simplified by async/await. Take a look at “pyramid of doom”. Reactive-approach is also trying to resolve that issue.
Personally I faced with async/await in C#. In Swift method which uses await
should be marked by async
Currently I don’t get how to call async method from sync one without using async{Detach} or similar constructs.
In C# I could call asynchronous method from synchronous due to extensions in Task.
Let's say we have onAppear async method in viewModel.
We can call it from SwitUI in "detached" block:
async{Detached} in Swift is kind of C#’s Task extension:
In reality async{Detached} returns a task which is active until ended or explicitly cancelled
Exploring Task (located in _Concurrent framework) struct we can see that its’ development is moving into direction of static methods. Task’s property can be inferred from calling context:
The simple way of joining task is to wait completion of couple of tasks. It can be done by merging sequence of tasks, or by grouping them.
Grouping is controlled by with{Throwing}TaskGroup, which in closure operates by Task{Throwing}Group containing working tasks. Tasks could be cancelled by cancelAll() method, and checked by isCancelled property.
However, the group waits termination of the tasks returned from iteration task by task.
The left-side code snippet allows to run tasks in parallel.
Also the great way to suspend a task and return results in completion handler, which is described in Apple’s Coffee Tracker is to use “continuation”. Take a look at elegant code from the tracker:
Actors:
Allows to provide exclusive access to its state, just for only one task. Actors like classes are reference types, but primarily developed for asynchronous execution.
MainActor, also the actor running on main thread.
DispatchQueue.main.async {... }can be replaced by MainActor.run { ... }, but should be used in the scope of async programming
Entities can be declared as MainActors (accessed from main thread ). However, confirmance them to protocol doesn’t look as an easy task.
In C# I remember there was async iterator, which could yield new value asynchronously. I guess similar construction is going to be added to Swift.
In this article we considered async/await improvements in Swift5.5. Such features could be tried in Xcode 13, which is in beta now. Don’t forget about official documentation and the code.
Sample project can be found at GitHub