Handle Multiple Async Callbacks with DispatchGroup
The first time I heard of a DispatchGroup was a few years into my iOS career - my teammate mentioned that he used it in his pull request code. He said this DispatchGroup made it easy to wait for multiple async callbacks to complete before doing some additional work. I wondered how I had never heard of it before! Letâs take a look at what he meant with a concrete code example.
Letâs say I have 3 different callbacks and want to do something after all 3 have finished. We might have some initial code that looks like this:
If youâve ever worked on something like this, maybe youâve asked yourself what the cleanest solution is to ensure that all the callbacks are run before you do any more work. Over the years Iâve had several solutions come to mind:Â
1. We could create boolean variables that correspond to each callback, each with an initial value of false. When a callback runs, set its corresponding variable to true & then check to see if all the âcallback completedâ variables are true. If none are false, then we know all the callbacks have run. This works, but it can get messy or impossible as more callbacks are added or if you have an unknown number of callbacks to manage (maybe you loop over an array of users & need to get info for each of them). This solution is starting to feel like the wrong one.
2. Another possibility would be to store an Int type variable to act as a counter. It will initially be zero, and weâll increment it right before each API call is started. Then, in each callback, decrement the value and check if itâs back to zero - when the counter gets back down to zero, you know that all callbacks have completed. This approach also works & allows us to keep track of an infinite number of callbacks. But did you know that Apple has already abstracted this logic into a simple object called DispatchGroup?
To use a dispatch group, simply initialize one and call the enter() method before each API call, then in each callback call leave() (youâll most likely want to call leave() at the end of the callback code, after youâve stored any data returned). The last step is to set up the dispatch groupâs callback with notify(qos:flags:queue:work:) so you can do whatever work is needed after all callbacks have completed. Hereâs our initial code from above with a DispatchGroup implemented:
I love the simplicity Apple has given us here - we simply tell the DispatchGroup when async blocks have started and finished, and define work to be done afterwards (being careful to think about which queue it should be run on đ ). Back when I learned about this, I couldnât believe it took so long for me to hear about them. Then again Apple has given us quite a few tools & Iâm not sure how one would learn about all of them except by reading through the entire standard libraryâŠ
In any case, I hope this article was enlightening and helpful - hopefully you were able to learn about the helpful DispatchGroup class earlier in your career than I did! Until next time âđŒ