iOS Concurrency with GCD & Operations
Sep 12 2023 · Swift 5.8, macOS 13, iOS 16, Xcode 14.3
Part 1: Grand Central Dispatch
Notes: 01. Introduction
Hi, I’m Audrey. Welcome to our course iOS Concurrency with GCD & Operations! In this video, you’ll find out what’s in store for you as you work through this course.
This is an intermediate course. You should be familiar with using asynchronous APIs like
URLSession. Check out this tutorial link if you need a refresher.
Let’s start by answering four questions.
First, WHAT is concurrency? It’s more than one task running “at the same time”. And a task is a set of instructions that accomplish some goal, like downloading an image or refreshing a list. Communication problems can happen, but these problems are easier to handle or avoid when you use a concurrency framework like GCD, Operations or Swift concurrency.
Second, WHY does your app need concurrency? To keep the user interface responsive. A common problem that concurrency solves is a scrollview of images that just will not scroll properly while the app is downloading & transforming the images. These are slow non-UI tasks that should run “somewhere else”, & that means concurrency.
Third, HOW do you use concurrency? By structuring your app so some tasks can run at the same time.
Tasks that modify the same resource must not run at the same time, unless the resource is threadsafe. We’ll cover thread safety in Part 2 of this course.
Tasks that access different resources, or only read values, can run at the same time. You use GCD & Operations to tell the system which is which, & then let it manage everything. :]
And final fourth: In 2021, Apple introduced its new Swift concurrency framework with async/await and actors, making it much easier and safer to use concurrency in your apps. This course lets you get more hands-on with concurrency and will enable you to work with code that uses GCD and Operations. For example, the CloudKit framework includes custom operations.
To answer that third question, I introduced the word threadsafe — so what’s a thread? Well, thread is short for thread of execution: It’s where a task runs. To run two tasks at the same time, your app needs at least two threads of execution. Threads are the lowest level of execution. They’re what Xcode’s Debug navigator shows you.
Here’s the ImageGrid app from the starter folder running in a simulator. It’s a SwiftUI version of the app in our Concurrency book.
This is an example of an app that needs concurrency. It downloads images to display in a grid view. As you can see, it just does not want to scroll while this is happening.
I’ve selected CPU in the Debug navigator to see the thread activity. Thread 1, where your app’s user interface runs, does roughly as much work as the other threads. Thread 1 is the main thread. It really should not be doing non-user-interface work at the same time it’s trying to update the user interface.
Now here’s the final project running: Scrolling is much smoother, but the images don’t appear as quickly because the main thread isn’t downloading them.
There are more threads doing the downloading work while the main thread just displays the images.
This course builds your knowledge of the tools you need to make all your apps behave like this. Don’t worry, the system handles all this thread creation and scheduling: You won’t find any explicit code about threads in either of these projects. You can create and manage threads directly — that’s what programmers did in the bad old days — but without the system’s knowledge of the load & hardware, your tasks might produce a thread explosion that slows down or even crashes your app, instead of speeding up its response. This course shows you how to use GCD and Operations to set up your tasks, & let the system manage the threads.
So what is GCD? Grand Central Dispatch is Apple’s catchy name for the underlying lib-dispatch library of the C programming language. Swift 3 updated the syntax to make it look like a normal Swift class.
GCD provides five global dispatch queues, as well as the main queue, your app’s user interface. GCD queues run on threads. Programming threads is messy; dispatch queues provide a higher-level abstraction — a wrapper around this messiness. Being queues, they’re First In First Out, where Out means start: tasks start in the order they arrive. But tasks running on a global queue might finish in a different order. This is because global queues are concurrent: They can run more than one instruction at a time by creating more than one thread.
The main queue is serial: It executes only one instruction at a time, and it runs on only one thread, called the main thread.
Operations wrap object-oriented convenience around dispatch queues. Operations are highly reusable: You can specify inputs, outputs and helper methods. You can cancel a running operation, or define dependencies on other operations. Most of the time, you add operations to an Operation-Queue which defaults to running on a global queue, off the main queue.
WHICH to use? The rest of this course will show you what each can do, but in general, GCD is easier to use for simple jobs, and Operations make it easier to do complex jobs. Simple vs complex generally refers to the amount of communication you need between tasks & how closely you want to monitor their execution.
Here’s what you’ll learn in this part of the course:
First, you’ll learn some basic uses of dispatch queues, and get your head around the terminology:
concurrent and serial,
synchronous and asynchronous. You’ll use your new skills to fix the image download problem in our sample project.
Next, you’ll learn how to group related tasks in a dispatch group, and receive notification when all the tasks finish. This is also where you’ll learn how to wrap an asynchronous function so you can use it in a dispatch group.
And then there are two more parts to this course:
In Part 2, you’ll learn about concurrency hazards: race conditions, deadlocks and priority inversion, and how to avoid them. And how to make your code thread-safe.
Part 3 covers Operations and Operation-Queues, and
you’ll learn how to create and subclass an AsyncOperation class so you can use it in an operation queue.
And finally, you’ll learn how to manage dependencies and cancellation in operation queues.
This course is an update of the update to the video course Introducing concurrency, by the amazing Sam Davies, star of numerous video courses and our Chief Technology Officer.
Scott Grosch wrote a book based on the UIKit version of this course, adding chapters on topics like semaphores and Core Data.
This video course was tech edited by Ehab Amer, an author of our Swift Apprentice books.
And Marco Santarossa was the final pass editor for this video course.
That’s it for this introductory video. I hope you enjoyed this video, thanks for watching and we’ll see you next time.