DispatchQueue - Magic in the Mystery

Why this simple code can solve 99% of bugs in your Swift code

Welcome to the first edition of [ between the brackets ]!

What even is this newsletter

I decided to start this newsletter after a few years of working on side project after side project. With each project, I usually learn something new and pretty interesting - so now I’m sharing it with all of you! If you find yourself programming in your free time, trying to learn how to code, or just like to learn new things this might be for you.

This week when developing a new social app, I dove deep into Swift’s DispatchQueue. It possess powers that can make or break your app's performance, but is generally a bit of a mystery at first glance. A rule of thumb followed by many Swift developers is ‘if it doesn’t work, throw it in a DispatchQueue’, but maybe its time we figure out what happens between the brackets.

The Power of DispatchQueue

Picture a bustling restaurant during the dinner rush. There are orders coming in left and right, with the kitchen hustling to keep up. The chef, managing the orders, is your app's DispatchQueue. It accepts tasks and decides how and when they're going to be cooked up, or in our case, executed.

Let's cook up a simple order:

let queue = DispatchQueue(label: "com.myapp.orderqueue")

queue.async {

    print("Cooking up your order in the kitchen!")

}

In this example, we've created a dispatch queue labeled com.myapp.orderqueue, and we've asked it to cook up an order in the background. Your patrons, in this case the users, can continue enjoying their drinks while their orders are being prepared.

The Benefits - It's All Gravy!

Now let's talk about the delicious benefits of using DispatchQueue. Its ability to execute tasks asynchronously is its main attraction. Think about a barista who can simultaneously prepare an espresso and a latte, instead of waiting for the espresso to be finished before starting on the latte.

DispatchQueue also helps prevent a situation akin to too many cooks in the kitchen. Too many threads can slow down your app, so DispatchQueue manages this by using global concurrent queues for tasks, which helps reduce the number of threads needed and keep your app running smoothly.

The Pitfalls - Don't Get Burned!

Every rose has its thorns, and DispatchQueue is no exception. It does have a few pitfalls you should be aware of. The biggest being trying to execute a work item synchronously on the main queue is like asking your patrons to wait until the restaurant is empty before allowing them to leave - it results in a deadlock.

Excessive thread creation is another hazard. It's akin to hiring more cooks than your kitchen can accommodate. If you create too many private concurrent dispatch queues, you could end up with too many cooks (too many threads). This could lead to the system running out of threads for your app, causing it to hang or crash.

Synchronous vs Asynchronous Execution

Let's delve into the synchronous vs asynchronous debate. When you schedule a work item, you have the option to execute it synchronously or asynchronously.

Let's say you're the owner of a small coffee shop. When a customer places an order, you can either choose to prepare the order yourself (synchronous), making the customer wait till you're done, or you could delegate the task to an employee and continue taking other orders (asynchronous).

Here's a technical comparison:

Synchronous execution:
let queue = DispatchQueue(label: "com.myapp.coffeeshop")

queue.sync {

    print("I'm preparing the order myself.")

}

print("Now that I'm done, I can take the next order!")
Asynchronous execution:
let queue = DispatchQueue(label: "com.myapp.coffeeshop")

queue.async {

    print("I've delegated the order preparation.")

}

print("I'm free to take more orders while the last one is being prepared!")

Synchronous execution means your code pauses until the work item is done, while asynchronous execution means your code just keeps on running, letting the work item complete in its own time.

When to Use and When Not to Use DispatchQueue

DispatchQueue is your best friend when you have tasks that need to be performed in the background, such as fetching data from a server, performing complex calculations, or handling time-consuming operations that don't need to be completed immediately.

However, if the tasks you're dealing with are UI-related or need to be completed before anything else can happen, you might want to think twice before employing DispatchQueue. Remember, all UI updates should be done on the main thread, and attempting to synchronously execute a work item on the main queue can lead to a deadlock.

Wrapping Up

DispatchQueue is an incredibly powerful tool in your Swift arsenal, helping you manage and optimize your app's performance. But, like any tool, it requires a good understanding and careful handling. Understanding when to use DispatchQueue, and when not to, can make the difference between an app that runs smoothly and an app that frustrates users with slow responses or crashes.

[ Zach ]