Concurrent Computing and Programming with Grand Central Dispatch
We are going to study concurent programming with Swift on iOS using the native Grand Central Dispatch (
GCD ) framework. If you are not familiar with concurrent programming I suggest you start by taking a look at wikipedia . Let’s get started by studying the philosophy and good practises behind this API.
Grand Central Dispatch
GCD (Grand Central Dispatch) is a framework that provides low-level APIs to handle concurrent programming on iOS, macOS, tvOS and watchOS platforms. All of the higher-level frameworks that offer competitive management at Apple, such as
NSOperation, are based on
GCD. These APIs allow you to divide the work of a process into individual tasks, and then help orchestrate the execution of these tasks in parallel or sequentially using a queue. It allows us to abstract from the notion of thread, processor or heart, and optimizes resource management at the same time with its own thread-pool.
A fundamental notion on which
GCD is based is FIFO (First In, First Out). The tasks that we want to execute will first be inserted into these queues, then GCD will come to retrieve them individually to dispatch them to the right threads / processors / hearts. We can distinguish 2 kinds of file:
- Concurrent file: Performs multiple tasks in parallel
- Sequential or Serial file: performs one-to-one tasks in series
Here are the 3 categories of existing files:
Main queue: equivalent to the main thread that primarily handles the application's UI. All of the UI calls must be done on this queue.
Global queue: the system provides us with 3 global tails with different priorities (HIGH, DEFAULT and LOW). These 3 files are of the Concurrent type.
Custom queue: queues that can be created manually and of the desired type (Serial or concurrent).
GCD in Practice
Let’s start by creating one of the 3 categories of queues:
For the creation of a custom queue , we first define an identifier (it is recommended to use the reverse-DNS format).
Now that we know how to create files, how do we use them? It’s very simple, thanks to the “dispatcher”! Here is a small example:
Let’s break down all that. We get to start a low priority queue. Then we “dispatch” a block of code asynchronously on the low priority queue previously recovered. This code block asynchronously fetch data to store it in the
data variable. Finally we update our
view in the main thread with the data recovered. It is important to perform the last step in the main thread because
UIKit is not threadsafe and if you update your components in another thread your application may crash or have undefined behavior.
Here the console will show:
inside async block
inside main Queue block
GCD you can manage all that concerns the concurrent programming. We will see in this section different cases of use a little further.
Let’s discuss a use case where you have several tasks to perform and you want to wait until all these tasks are done before doing anything else. For this it is necessary to use the
In order to wait for all the tasks to be done we create a
group and in our loop we define when a task starts in the group and especially define when the task is finished. We must imagine this as a counter, each
enter this counter is incremented by 1, and each
leave it is decremented by 1. At the end we define a
notif bloc which listens to the counter of the
group and which executes the block in the given
queue when he gets to 0. The console output here would be: (Finished job order may differ)
Starting job 0
Starting job 1
Starting job 2
Starting job 3
Starting job 4
Starting job 5
Starting job 6
Starting job 7
Starting job 8
Starting job 9Finished job 3
Finished job 2
Finished job 1
Finished job 4
Finished job 0
Finished job 9
Finished job 5
Finished job 6
Finished job 8
Finished job 7All jobs done!
A second very useful case may be wanting to execute code after a certain time. If you have this kind of case immediately think about
GCD and its
GCD is a very powerful framework that allows you to really get away from the low-level constraints inherent in concurrent programming. However to fully use it to this potential, you need to be careful with shared memory problems and syncronization. Take a deeper look here.