async-await in swift

Vikash Anand
5 min readJul 4, 2021

--

Disclaimer — This is less of an article and more of a note that I have created after reading “async-await” articles and watching “Meet async-await in Swift” WWDC 21 video.

Hopefully this will clarify some of the doubts that you have regarding “async-await in Swift”. So, lets get straight into the topic.

Note — I am planning to write more on this topic and this article will be update accordingly in the future.

— — — — — — — — — — — — — — — — — —
Synchronous function

A synchronous function is one that executes all its work in a simple, straight line on a single thread.

Example

Problem

  • Synchronous function calls are blocking calls.

Asynchronous functions

Types

1. Asynchronous functions with completion handlers

2. Asynchronous functions with delegation call-backs e.g. Location APIs delegates

3. Asynchronous functions marked with async keyword — New in Swift 5.5

Example of an asynchronous function with async keyword

func fetchImage(for id: String) async -> UIImage

Asynchronous functions with completion handlers

//Fetching an image over the network and then converting it into a thumbnail and returning it

Problem — Swift can’t check our work

  • Can’t enforce invocation of completion handlers for all possible cases — It’s very easy to forgot calling the completion handler and In Swift there is no way to enforce that a completion handler is always invoked.
  • Can’t use swift’s usual error handling mechanism — A synchronous function can either return a value or throw an error and swift ensures that if a value is not returned an error is thrown. But we can’t just throw an error from a completion handler.

async — await to the rescue

//Fetching an image over the network and then converting it into a thumbnail and returning it

Syntax — Things to notice

  • When you mark a function as async, the keyword should go just before “throws” in the function signature, i.e. just before the arrow if the function doesn’t throw.
  • “try” is here because the data method is marked “throws”.
  • Just as try is needed to call a function marked as throws, await is need to call a function marked as async.

What async keyword indicates?

  • A function marked async is allowed to be suspended and when it suspends itself then it suspends its callers too, so callers must be async too.

What await keyword indicates?

  • Await keyword is used to point out where in an async function it might suspend.

Throwing function analogy

  • While an async function may suspend, just because it marked as async doesn’t necessarily mean it will suspend, just like a function marked as throws doesn’t mean that it will always through an error, it may or may not throw.
  • Similarly, just because await is mentioned doesn’t mean function will definitely suspend there, just like using a “try” keyword just before calling a function that can throw an error.

Synchronous vs async — Difference in the control flow

Synchronous calls

Image Source — https://developer.apple.com/videos/play/wwdc2021/10132/

Async calls

Image Source — https://developer.apple.com/videos/play/wwdc2021/10132/

Important points

  • Async function can suspend as many times as it needs to
  • While an async function may suspend, just because it marked as async doesn’t necessarily mean it will suspend.
  • Similarly, just because await is mentioned doesn’t mean function will definitely suspend there.
  • But eventually whether an async function suspends or not, after finishing it will return the control of the thread to the calling function along with a value or error.
  • A function may resume onto an entirely different thread.

Another async-await control flow example

async properties and initializers

  • Not just functions but properties can be async too and so can initializers.

Things to notice

  • Only read-only properties can be async
  • Property getters can also throw

If an expression has multiple async function calls, you only need to write await once, just like you only need one “try” for an expression with multiple throwing calls.

URLSession — Syntax comparison between completion handler vs async-await versions

Completion handler version

Declared under NSURLSession Category (Objective — c)

async-await version

Declared under URLSession extension

Things to notice

  • In the async version, no need to add “resume()” to invoke a data task.
  • async version returns non-optional data and response and in case of failure it throws an exception which makes it lot easier to handle at the call site as now there is no need to add extra logic to handle optional data or error.

XCTest supports async

Testing an asynchronous methods — completion handler approach.

Testing an asynchronous method — async-await approach

Things to notice

  • In the async version, no need to set an expectation for an asynchronous function.

Xcode — 13 Tip

  • Xcode 13 has a new option to convert an asynchronous function with completion handler approach to an asynchronous function with async-await approach.
  • CMD + left click on an asynchronous function with completion handler approach with present the conversion option.

Result after conversion

Conclusion

That’s it for now, thanks for reading. Also if you really find this helpful then please leave some applause to this article.😀😀😀

Resources

- Meet async/await in swift — WWDC 2021

--

--