Pursuing async/await

Siarhei Yakushevich
Nerd For Tech
Published in
3 min readJul 4, 2021

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 asyncCurrently 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.

Can’t call from synchronous method, right?
Let's say we have onAppear async method in viewModel. 
We can call it from SwitUI in "detached" block:
Calling VM’s async from SwiftUI

async{Detached} in Swift is kind of C#’s Task extension:

From WWDC’s slide
Calling “synchronously” asynchronous method

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.

Merging tasks sequentially

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:

Returning results to completion block

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.

Conformance to protocol looks tricky

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

--

--