Categories
apple ios

Limit Concurrent Network Requests With DispatchSemaphore in Swift

First, let’s create a URL, a background DispatchQueue, and a DispatchSemaphore with a worth of 2:

The worth parameter of the semaphore signifies the utmost collection of concurrent operations allowed. In different phrases, we will be able to permit most effective two photographs to be fetched on the identical time.

Now, let’s upload one way referred to as loadRandomPhoto() and create an async job:

Add semaphore.wait() and semaphore.sign() within the job frame, as follows:

The semaphore.wait() command decrements the semaphore counter by means of 1. We have set the counter to 2 when initializing the DispatchSemaphore, so as soon as the loadRandomPhoto() serve as is administered, the worth is diminished by means of 1.

The semaphore.sign() command will increase the counter of the semaphore, which means that an operation is completed and any other one can take its position.

We wish to run the semaphore.sign() command on the finish of the async job. The defer remark very easily achieves that, so we don’t wish to concern about putting the command within the unsuitable position.

Now let’s fetch Data from the url belongings:

For debugging functions, we merely print the UIImage received from Data.

Great! Now we need to release a number of symbol loading operations and apply the output:

As we will be able to see, the for loop fires the loadRandomPhoto() serve as ten instances.

Now, if we run the Xcode Playground, we will be able to see photographs published in batches of two:

The semaphores are achieved, however what’s the adaptation between the usage of a sync execution and an async one?

When the usage of sync, the thread on which it was once referred to as will likely be blocked till the duty is completed, whilst an async execution doesn’t stay up for a job to finish. Therefore, it doesn’t block the present thread.

In our instance, let’s take away the DispatchSemaphore and alter the async execution to a sync one:

As a end result, we see photographs loading most effective one at a time:

So, the usage of sync produces the similar end result when the usage of a DispatchSemaphore with a worth set to 1.

However, in our case above, although we specified the .background high quality of carrier of the DispatchQueue, the sync name nonetheless occurs at the major thread. As a end result, we’ve got the picture loading operations freezing our UI till they’re completed.

Therefore, it’s higher to be very cautious when calling sync at the DispatchQueue.major. If we name it from the principle thread, the app will terminate because of impasse. On the opposite hand, when it is named from the background thread, we must steer clear of including to it a time-consuming block of code to forestall the UI from freezing.