Showing modals as a result for a requests (look at the semaphores)

Last week, I talked to another iOS developer about a classic problem encountered during development that, for sure, if you have participated in a selection process for an iOS mobile developer job, you have likely faced.

“How do you execute a process after a request, one at a time, when your requests run in parallel?”

It was then that the idea for this post came to mind.

Let’s see now how we managed to resolve this situation.

GCD – The inglorious saviour

Many people fear these letters more than anything when they need to do something asynchronously on iOS.


If used correctly, Grand Central Dispatch (GCD) can save you and provide an incredible user experience.

If used incorrectly, it can drive you crazy with practically “undebuggable” errors, almost impossible to reproduce scenarios, memory corruption, and chaos.

It is an inglorious saviour: it can get you out of disaster, but it can also take you to a much worse one.

GCD goes far beyond the famous asyncs that developers use to send a process to a background thread or bring processing back to the main thread. It has very useful resources for different types of situations, such as DispatchGroups, DispatchSemaphores, and QoS for Global Threads; but today I want to talk a little bit about just one of these features: DispatchSemaphores.

Imagine a situation where a process can be run multiple times, but only one run at a time.

It would be simple if we think of a single-threaded environment. Processing would end, and run again.

#blindPeople: the image shows several processes being executed in a chain, one after the other, in a cycle like “process, screen, process”.

But in a multi-threaded environment, this becomes an issue. How do I know if the processing is finished to start the next one? How do I make processing wait to start the next one if the previous one is still running?

#blindPeople: the image shows several processes being directed to a stack, which is directed to the screen.

That’s where queues and semaphores come in.

Queues and Semaphores

First, we need to create a queue in the background to carry out the execution of our process, which in our case will be to create and display a modal in our app.

For this, we created a DispatchQueue. When creating a Queue, we basically have two creation options, based on how the Queue will execute the tasks it receives:

Serial: a queue-running execution (FIFO), where one process is performed at a time, in the order of entry.

Concurrent: a concurrent execution queue, where each process runs on its own thread, and they run in parallel.

In our case, we’ll create a Serial queue, as our execution will be based on the input order, one at a time.

private let dispatchQueue = DispatchQueue(label: "dev.andresalla.DispatchTest.ModalPresenter")

So we solved our problem of opening modals, right?


Since we aren’t on the main thread, we send the modal opening asynchronously to the main thread. After this dispatch, the execution of our process ends, and the next one in the queue starts executing.

How do we make it wait for the next execution until the modal closes? Simple: we’ll use a semaphore.

Semaphores allow you to wait (wait method) until they have free resources to continue.

When you create a semaphore, you specify the number of “resources” it has, that is, the number of times it can pass through the wait method before it has to wait for some resource to be released (signal method) to proceed with its execution.

In this way, we create our semaphore to allow one resource at a time, and ask it to wait in our queue (wait) until the modal is closed.

private let dispatchSemaphore = DispatchSemaphore(value: 1)

But how do we know if the modal has been closed so we can release the resource?

Let’s create a callback!

One callback to rule them all

Our callback will be called in the modal, at dismiss, so that we can release the resource of our semaphore.

For this, we created a ModalPresentable Protocol, with a dismissAction variable, which will be executed when the modal is dismissed.

When we put our modal in the queue for presentation, we will require it to conform to UIViewController and ModalPresentable.

In this way, we can implement the release (signal) of our resource with the semaphore.

protocol ModalPresentable: AnyObject {
    var dismissAction: (() -> Void)? { get set }

class ViewController: UIViewController {

    private let dispatchQueue = DispatchQueue(label: "dev.andresalla.DispatchTest.ModalPresenter")
    private let dispatchSemaphore = DispatchSemaphore(value: 1)

    // Outras variáveis e constantes

    func presentModal(_ viewController: UIViewController & ModalPresentable) {
        dispatchQueue.async { [weak self] in
            DispatchQueue.main.async {
                viewController.dismissAction = { [weak self] in
                self?.present(viewController, animated: true, completion: nil)

    // Outros métodos

Run baby, run

And it’s done! Our screens will be displayed sequentially, without overlapping, and will be displayed when its predecessor (if any) is closed.

#blindPeople: the image is an animation showing two screens, one purple and one red, being displayed sequentially, one after the other, over a white screen.

I hope this tip is useful for you! More to come soon!