I have the following code:
func testFunc(completion: (Bool) -> Void) {
let queue = NSOperationQueue()
queue.maxConcurrentOperationCount = 1
for i in 1...3 {
queue.addOperationWithBlock{
Alamofire.request(.GET, "https://httpbin.org/get").responseJSON { response in
switch (response.result){
case .Failure:
print("error")
break;
case .Success:
print("i = \(i)")
}
}
}
//queue.addOperationAfterLast(operation)
}
queue.waitUntilAllOperationsAreFinished()
print("finished")
}
and output is:
finished
i = 3
i = 1
i = 2
but I expect the following:
i = 3
i = 1
i = 2
finished
So, why queue.waitUntilAllOperationsAreFinished() don't wait?
Each operation you've added into queue is immediately executed because Alamofire.request
simply returns without waiting for the response data.
Furthermore, there is a possibility of deadlock there. Since responseJSON
block is executed within the main queue by default, blocking the main thread by calling waitUntilAllOperationsAreFinished
will prevent it from executing the completion block at all.
First, in order to fix the deadlock issue, you can tell Alamofire to execute the completion block in a different queue, second, you can use dispatch_group_t
to group the number of asynchronous HTTP requests and keep the main thread waiting till all those requests in the group finish executing:
let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)
let group = dispatch_group_create()
for i in 1...3 {
dispatch_group_enter(group)
Alamofire.request(.GET, "https://httpbin.org/get").responseJSON(queue: queue, options: .AllowFragments) { response in
print(i)
dispatch_async(dispatch_get_main_queue()) {
// Main thread is still blocked. You can update the UI here but it will take effect after all HTTP requests are finished.
}
dispatch_group_leave(group)
}
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
print("finished")