Modern Concurrency: Beyond the Basics

Build on your knowledge of async/await, tasks and asynchronous sequences to use concurrent tasks in safe, performant and predictable asynchronous apps. Learn how to create and use custom AsyncStream sequences, continuations, task groups and custom actors. By Audrey Tam.

5 (2) · 1 Review

Download materials
Save for later

Learning path

This is part of the Concurrency in iOS learning path. View path.

Who is this for?

This course is for intermediate Swift developers who are familiar with writing asynchronous applications with async/await, tasks and asynchronous sequences, and want to use custom AsyncStream sequences, continuations, task groups and custom actors to write safer and more predictable asynchronous apps.

Covered concepts

  • AsyncStream
  • Manual continuations
  • Unit testing & testing tools
  • Task groups
  • Custom actors
  • Global actors

Part 1: AsyncStream & Continuations

Toggle description

Get an overview of what’s in this course and take a closer look at what you’ll learn in Part 1 — AsyncStream, continuations, unit testing. Get introduced to the messaging app you’ll work on and review what you need to work through this course.

AsyncStream 12:14
Toggle description

AsyncStream is an easier way to create a custom AsyncSequence. Convert the Typewriter AsyncSequence from the previous course to unfolding (pull-based) and buffered (push-based) AsyncStreams.

Toggle description

Run the course server. Get an overview of Blabber’s chat() function. Implement a countdown timer as an unfolding AsyncStream.

Toggle description

Wrap the synchronous Notifications API in a buffered AsyncStream to produce system messages when users leave the chat and return.

Toggle description

Challenge: Rewrite countdown(to:) using the buffered push-based version of AsyncStream and Timer.scheduledTimer.

Unit Testing 24:02
Toggle description

Add unit tests for the BlabberModel type: To verify that BlabberModel sends correct data to the server, you’ll configure a custom URLSession for your tests to work with, write unit tests for say(_:) and countdown(to:), and note timeout and duration issues that you’ll fix in Episode 9 Unit Testing Tools.

Toggle description

To implement the location button in Blabber, you’ll use a manual continuation to integrate the Core Location manager delegate pattern with Swift concurrency. You’ll inject a manual continuation into a custom Core Location manager delegate and use this to implement its delegate methods. This is a good way to handle a fixed number of delegate method calls.

Toggle description

The starter project contains a custom AddressCoder to convert a location into the nearest address. To simulate a callback API, its method addressFor(location:) requires a completion handler. You’ll wrap this in a manual continuation to post the user’s address as a Blabber message.

Toggle description

When you wrote unit tests in episode 6, there were two issues: await doesn’t time out, and the tests take more than 5 seconds to run, because of the 1-second waits built into the countdown. In this episode, you’ll create unit testing tools to fix these issues: You’ll create a timeout mechanism, and you’ll speed up execution with a custom sleep function.

Conclusion 1:33
Toggle description

Review what you learned in Part 1 and see what’s coming up in Part 2.

Part 2: Concurrent Code

Toggle description

Learn how to use TaskGroup for truly dynamic concurrency and how to use the Actor API to make your code thread-safe. Learn about the apps you’ll build in this part of the course and the Swift concurrency tools you’ll use.

TaskGroup 13:52
Toggle description

Learn how to use TaskGroup to create concurrency on the fly. The image download tasks in Sky are independent, so you can run them concurrently. Add them to a task group and set their priority to promote UI updates.

Toggle description

Learn how to safely process the results of concurrent tasks in a TaskGroup and control the number of tasks running in parallel.

Actor 12:58
Toggle description

The EmojiArt app runs a lot of tasks in parallel: Concurrent tasks add downloaded images to a collection and update progress values, so there’s a lot of potential for data races. Learn how to use the Actor protocol to protect shared mutable state and convert EmojiArtModel from a class to an actor.

Examine the ImageLoader actor and use it to provide an in-memory image cache for the EmojiArt app.

Toggle description

Learn how to create custom global actors, just like MainActor, for situations where you need a single, shared actor that’s accessible from anywhere.

Toggle description

Create a custom GlobalActor to provide a persistent, on-disk image cache that allows easy and safe access to shared resources from anywhere in your app.

Toggle description

Use your ImageDatabase global actor to provide an on-disk image cache for the EmojiArt app. Implement the in-memory cache hit counter and clear button.

Toggle description

Challenge: Implement the on-disk cache hit counter and clear button.

Conclusion 1:16
Toggle description

Review what you learned in this course.

Up next

iOS & Swift
iOS Concurrency with GCD & Operations
Learn how to add concurrency to your apps! Keep your app’s UI responsive to give your users a great user e... more



Audrey Tam


Adrian Strahan

Tech Editor

Adriana Kutenko


Nicolai Martelle Manaloto

Video Editor

Over 300 content creators. Join our team.