I have a project with 2 sets of async functions which should be executed in order. After all async functions are executed, I'm trying to run function3
.
Here is a high level structure of my code:
class VC: UIViewController {
let dispatchGroup = DispatchGroup()
let dispatchGroup2 = DispatchGroup()
override func viewDidLoad() {
asyncFunc1()
dispatchGroup.notify(queue: .main) {
asyncFunc2()
}
dispatchGroup2.notify(queue: .main) {
print("all done")
function3()
}
}
func asyncFunc1() {
for item in itemArray {
dispatchGroup.enter()
Alamofire.request(urlString).responseString { response in
dispatchGroup.leave()
}
}
}
func asyncFunc2() {
for item in itemArray2 {
dispatchGroup2.enter()
Alamofire.request(urlString).responseString { response in
dispatchGroup2.leave()
}
}
}
}
My expectation is that functions run in order of asyncFunc1() -> asyncFunc2() -> function3()
.
When I actually run this app, I see that dispatchGroup2.notify
is triggered at the beginning when program runs and never gets called after asyncFunc2
is done. What's wrong over here? I've tried doing with one dispatchGroup
variable instead of having 2 (dispatchGroup
and dispatchGroup2
) but this didn't work again.
I would recommend a simple refactoring to encapsulate those DispatchGroup
s inside the corresponding asynchronous functions:
func asyncFunc(completion: @escaping () -> Void) {
let dispatchGroup = DispatchGroup()
for ... {
dispatchGroup.enter()
request ... {
dispatchGroup.leave()
}
}
dispatchGroup.notify(queue: .main) {
completion() // Async function completed!
}
}
This would result in a very nice/compact top-level solution:
asyncFunc1 {
self.asyncFunc2 {
print("all done")
self.function3()
}
}
Initial bug. Your original issue was caused by calling notify(queue:)
before the corresponding enter()
method. Your dispatch group was over even before it began ;)