Grand Central Dispatch & DispatchQueue in Swift

Mammadowr
5 min readJul 31, 2022

--

Step-by-step we are learning a lot about Swift. If you did not read my previous articles yet, then please read below links, without previous knowledge, this article will not make any sense to you.

In this article, I will give detailed information about GCD and DispatchQueue.

Grand Central Dispatch (GCD)

Short answer: It is a low-level API that helps us to manage concurrent operations. It helps us to improve our app’s responsiveness by deferring computationally expensive tasks to the background.

Thread and Queues

I suppose you have heard at least once about Thread and DispatchQueue. If you are a fresh programmer, then maybe you did not hear about them yet, but I promise you that during your journey you will hear about them and you will use them a lot.

Thread and Queue are indispensable in the software world. In this article, I will explain you what DispatchQueue and Thread are.

Thread

Thread is a structure that allows more than one job to be done simultaneously. The maximum number of tasks of each thread is one, but we can define other threads within this thread. The situation where more than one nested threads are used is called multi-threading. Threads are actually of life-saving importance. By dividing the work to be done into threads, we can enable the completion of the work in a much faster or controlled manner than we aim.

The more cores there are in the CPU of our iOS Devices, the more Threads we can open at the same time. The more cores we have on our device, the faster device we have.

We can list the advantages of working in an iOS application by dividing it into multiple threads as follows:

  1. It breaks down the work to be done and allows them to run simultaneously. Rather than running in the queue, it causes the jobs that run simultaneously to finish much faster than the queue.
  2. Without interfering with the Main Thread, by advancing the processes in a new thread, you can finish the processes without the user knowing about the process and they can see that the application is not affected by this business process, that is, it does not slow down. It provides a great advantage in terms of performance.
  3. The optimisation of threads belongs entirely to Apple. We only use it through the API. If we want this control to be ours and not Apple’s, we need to use NSOperation.

DispatchQueue

When doing a job, we would not make a wrong definition if we say “DispatchQueue object” to complete the job in order by dividing the job into one or more threads according to the type of job. DispatchQueue works in first in first out logic (FIFO). It works synchronously or asynchronously, and is a group of APIs from Apple that helps us handle synchronous and asynchronous situations.

Main Queue

The main queue is created automatically when the application is opened. It is a queue responsible for the user interface. Unless it is a UI operation, we never want to do a job on the main queue simultaneously. For example, let’s assume that we take a picture from a server in the main queue simultaneously, it is inevitable that the UI will lock or stutter.

Quality of service (Qos)

In order for the tasks to be prioritised appropriately according to the work to be done, we need to define how important the task we queue is in the code and communicate it to iOS. We need to correctly specify which qos service we will use to iOS when high priority tasks need to be performed faster, an animation needs to be completed instantly, or a data needs to be accessed instantly when a button is clicked. The fact that things are using the right Quality of service (Qos) services allows us to prevent possible crashes.

The queue types that Qos offers us are as follows according to their jobs:

.background

We use the .background queue for tasks that we do not want the user to be aware of. It does not wait for an interaction from the user. They are not time sensitive. Restfull operations, database maintenance, synchronising remote servers and backups are among the examples we can give to understand the usage area of the .background queue. It is ideal for operations that will take minutes.

.utility

It is used in longer processes than .background and in jobs that do not need to be finished immediately. It should be assigned to tasks that will not prevent the user from using the application. It is used in operations such as data download, import, long calculations.

.userInitiated

It is used for user-initiated tasks that require immediate results, such as opening a saved document or performing an action when the user clicks something in the user interface. Work is required for user interaction to continue. Performance orientated.

.userInteractive

This queue is used for tasks that the user interacts with directly. If the work is not completed quickly, freezes may occur on the screen. It aims to finalise the given work instantly. We can give examples such as animation, UI refresh. Performance orientated.

.default

It is located between .userInitiated and .utility. We prefer not to use the Default queue because it is not designed to classify the work to be done like other queue types. When used, it is assumed that no queue information is assigned.

.unspecified

indicates that there is no undefined Qos information. I do not recommended you to use it.

DispatchWorkItem

It is used in jobs where the created queue will have cancellation or delay features. It allows a job that is in the queue but has not been processed to be cancelled. The important point here is that the job must not have started to be processed in the thread.

cancel()

When we want to finish the work done, we need the cancel() method.

notify()

It is a method that allows us to assign the next job after completing an existing job in the queue.

wait()

We use the wait() method to prevent the queue from moving to the next queue before the queued job is finished.

enter() and leave()

If wait() or notify() methods are used in an asynchronous structure, you will see that the asynchronous structure continues without waiting for the end of the code block, that is, it proceeds synchronously, and you will not know whether the asynchronous code block is over or not. This is where the enter() and leave() methods come in handy. If we want to be notified of the end of an asynchronous code block, we need to manually tell this to the group.

Basically that is all from my side. If you like my articles, if you think that they are useful, you can click on “Follow” button and share articles to reach more people. :)

--

--

Mammadowr

I speak 6 human and 5 programming languages. 🥳  iOS Developer. To support me: https://www.buymeacoffee.com/mammadowr8 ☕️