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.
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.
- Manual continuations
- Unit testing & testing tools
- Task groups
- Custom actors
- Global actors
Part 1: AsyncStream & Continuations
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 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.
Run the course server. Get an overview of Blabber’s
chat() function. Implement a countdown timer as an unfolding
Wrap the synchronous Notifications API in a buffered
AsyncStream to produce system messages when users leave the chat and return.
countdown(to:) using the buffered push-based version of
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
countdown(to:), and note timeout and duration issues that you’ll fix in Episode 9 Unit Testing Tools.
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.
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.
Unit Testing Tools
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
Review what you learned in Part 1 and see what’s coming up in Part 2.
Part 2: Concurrent Code
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.
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.
Learn how to safely process the results of concurrent tasks in a
TaskGroup and control the number of tasks running in parallel.
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.
ImageLoader actor and use it to provide an in-memory image cache for the EmojiArt app.
Learn how to create custom global actors, just like
MainActor, for situations where you need a single, shared actor that’s accessible from anywhere.
Creating a GlobalActor
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.
Using a GlobalActor
ImageDatabase global actor to provide an on-disk image cache for the EmojiArt app. Implement the in-memory cache hit counter and clear button.
Challenge: Implement the on-disk cache hit counter and clear button.
Review what you learned in this course.