Grand Central Dispatch Tutorial for Swift 5: Part 1/2
Learn all about multithreading, dispatch queues and concurrency in the first part of this Swift 5 tutorial on Grand Central Dispatch. By Fabrizio Brancati.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Grand Central Dispatch Tutorial for Swift 5: Part 1/2
30 mins
- Getting Started
- Breaking Down GCD Concepts
- Learning Concurrency
- Understanding Queues
- Understanding Queue Types
- Scheduling Synchronous vs. Asynchronous Functions
- Managing Tasks
- Handling Background Tasks
- Delaying Task Execution
- Managing Singletons
- Handling the Readers-Writers Problem
- Reasoning About Dispatch Barriers
- Where to Go From Here?
Grand Central Dispatch (GCD) is a low-level API for managing concurrent operations. It can help improve your app’s responsiveness by deferring computationally expensive tasks to the background. It’s an easier concurrency model to work with than locks and threads.
In this two-part Grand Central Dispatch tutorial, you’ll learn the ins and outs of GCD and its Swifty API. This first part explains what GCD does and showcases several basic GCD functions. In the second part, you’ll learn about some advanced functions GCD has to offer.
You’ll build upon an existing app called GooglyPuff. GooglyPuff is a non-optimized, “thread-unsafe” app that overlays googly eyes on detected faces using Core Image’s face detection API. You can select images on which to apply this effect from your photo library or download images from the internet.
Your mission is to use GCD to optimize the app and ensure you can safely call code from different threads.
This tutorial will help you to better understand how GCD works with serial and concurrent queues. It’s also beneficial to learn about these new asynchronous features that are now available.
async
and await
has arrived, and a massive set of improvements has also landed in the language.
This tutorial will help you to better understand how GCD works with serial and concurrent queues. It’s also beneficial to learn about these new asynchronous features that are now available.
In this Grand Central Dispatch tutorial, you’ll delve into basic GCD concepts, including:
- Multithreading
- Dispatch queues
- Concurrency
Getting Started
Use Download Materials at the top or bottom of this tutorial to download the starter project. Open it in Xcode, and run it to see what you have to work with.
CIDetector
work.The home screen is initially empty. Tap +, then select Le Internet to download predefined images from the internet. Tap the first image, and you’ll see googly eyes added to the face.
You’ll primarily work with four classes in this tutorial:
-
PhotoCollectionViewController
: The initial view controller. It displays the selected photos as thumbnails. -
PhotoDetailViewController
: Displays a selected photo fromPhotoCollectionViewController
and adds googly eyes to the image. -
Photo
: This protocol describes the properties of a photo. It provides an image, a thumbnail and their corresponding statuses. The project includes two classes that implement the protocol:-
DownloadPhoto
, which instantiates a photo from an instance ofURL
. -
AssetPhoto
, which instantiates a photo from an instance ofPHAsset
.
-
-
PhotoManager
: This manages all thePhoto
objects.
The app has a few problems. One that you may have noticed when running it is that the download complete alert is premature. You’ll fix this in the second part of the series.
In this first part, you’ll work on a few improvements, including optimizing the googly-fying process and making PhotoManager
thread-safe.
Breaking Down GCD Concepts
To understand GCD, you need to be comfortable with several concepts related to concurrency and threading.
Learning Concurrency
In iOS, a process or application consists of one or more threads. The operating system scheduler manages the threads independently of each other. Each thread can execute concurrently, but it’s up to the system to decide if, when and how it happens.
Single-core devices achieve concurrency through a method called time-slicing. They run one thread, perform a context switch, then run another thread.
Multi-core devices, on the other hand, execute multiple threads at the same time via parallelism.
GCD is built on top of threads. Under the hood, it manages a shared thread pool. With GCD, you add blocks of code or work items to dispatch queues and GCD decides which thread to execute them on.
As you structure your code, you’ll find code blocks that can run simultaneously and some that should not. This allows you to use GCD to take advantage of concurrent execution.
Note that GCD decides how much parallelism it requires based on the system and available system resources. It’s important to note that parallelism requires concurrency, but concurrency doesn’t guarantee parallelism.
Basically, concurrency is about structure while parallelism is about execution.
Understanding Queues
As mentioned before, GCD operates on dispatch queues through a class aptly named DispatchQueue
. You submit units of work to this queue, and GCD executes them in a FIFO order (first in, first out), guaranteeing that the first task submitted is the first one started.
Dispatch queues are thread-safe, meaning you can simultaneously access them from multiple threads. GCD’s benefits are apparent when you understand how dispatch queues provide thread safety to parts of your code. The key to this is to choose the right kind of dispatch queue and the right dispatching function to submit your work to the queue.
Queues can be either serial or concurrent. Serial queues guarantee that only one task runs at any given time. GCD controls the execution timing. You won’t know the amount of time between one task ending and the next one beginning:
Concurrent queues allow multiple tasks to run at the same time. The queue guarantees tasks start in the order you add them. Tasks can finish in any order, and you have no knowledge of the time it will take for the next task to start, nor the number of tasks running at any given time.
This is by design: Your code shouldn’t rely on these implementation details.
See the sample task execution below:
Notice how Task 1, Task 2 and Task 3 start quickly, one after the other. On the other hand, Task 1 took a while to start after Task 0. Also notice that while Task 3 started after Task 2, it finished before Task 2.
The decision of when to start a task is entirely up to GCD. If the execution time of one task overlaps with another, it’s up to GCD to determine if it should run on a different core — if one is available — or instead perform a context switch to run a different task.