Note: If you are a beginner and you find it difficult to understand things written in this article. Feel free to ask questions on my Reddit page or Twitter.
To Read How to use GCD (Grand Central Dispatch) in Swift? - Synchronous & Asynchronous Programming Tutorial. Click Here.
To Read the Difference between Concurrent Queue and Serial Queue. Click Here.
Remember, you can do it. 😉
I hope you guys have read both of my articles about GCD. If you haven't, then I have added links on top of this page in the notes section, so please read them.
Let's say we have a set of tasks assigned to our DispatchQueue, and we need to know when all of them are executed in some cases.
Some of us ignore using queues, thinking that we can't have a callback for the completion of all tasks. Or we try to achieve this behaviour with a lot of unnecessary lines of code.
Let’s dive into our topic of this article with examples.
What is DispatchGroup?
If you have heard about DispatchGroup, one of the questions that arrive in our mind is that, is it some form of DispatchQueue?
No, DispatchGroup is a subclass of DispatchObject, and it helps us group multiple queues regardless of their type (Concurrent or Serial). Next, We can set a completion callback to execute on any Thread (Main or Background) specified by us.
E.g.
// Create Group
let group = DispatchGroup()
// Date created for demo purposes
let date = Date()
// Create a Concurrent Queue
let queue = DispatchQueue(label: "com.swiftpal.dispatch.queue", attributes: .concurrent)
// Link the Queue to Group
queue.async(group: group) { // Group Linked
Thread.sleep(forTimeInterval: 3) // Wait for 3 seconds
let difference = Date().timeIntervalSince(date)
print("Task 1 Done with difference of \(difference.rounded()) seconds")
}
// Create a Serial queue
let queue2 = DispatchQueue(label: "com.swiftpal.dispatch.queue2")
// Link the Queue to Group
queue2.async(group: group) { // Group Linked
Thread.sleep(forTimeInterval: 1) // Wait for 1 second
let difference = Date().timeIntervalSince(date)
print("Task 2 Done with difference of \(difference.rounded()) seconds")
}
// Notify Completion of tasks on main thread.
group.notify(queue: DispatchQueue.main) {
// Update UI
Thread.sleep(forTimeInterval: 1) // Wait for 1 second
let difference = Date().timeIntervalSince(date)
print("All tasks executed with difference of \(difference.rounded()) seconds")
}
/* Output:
Task 2 Done with difference of 1.0 seconds
Task 1 Done with difference of 3.0 seconds
All tasks executed with difference of 4.0 seconds
*/
If you see in the code above, we start by creating a DispatchGroup and a Date object. The date object, in this case, is used to show you the time difference between the execution of each task.
Next, we created a Concurrent Queue with an async task, which is linked to the group we initialized on the first line.
Next, we created a Serial Queue with an async task, which is also linked to the same group.
Now to get a completion callback, we called the notify function from the group we declared earlier, and in the notify function, we requested to execute the completion task on the Main Thread.
At the bottom of the code, you can see the output with the difference in time since the Date object was created.
You can see that Task 2 completed it’s execution first and within one second. Task 1, on the other hand, took three seconds to complete. After both the tasks were executed, our completion block was called, and it took four seconds to perform due to the waiting time of queues and the sleep function we have added.
So, this was DispatchGroup; it is very easy to use and produces our desired result.
I hope you liked my article, there is so much more to explore in GCD, so subscribe to my article now and receive the latest updates about my new article.
If you have any suggestions or questions, Feel free to connect me on Twitter. 😉
To Read, What is QoS (Quality of Service) in GCD? Click Here.