如何等待所有NSOperations完成?

时间:2016-09-01 06:48:33

标签: ios swift nsoperation nsoperationqueue

我有以下代码:

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")
}

,输出为:

finished
i = 3
i = 1
i = 2

但我希望如下:

i = 3
i = 1
i = 2
finished

那么,为什么queue.waitUntilAllOperationsAreFinished()不等待?

3 个答案:

答案 0 :(得分:5)

您已添加到队列中的每个操作都会立即执行,因为Alamofire.request只是返回而不等待响应数据。

此外,存在死锁的可能性。由于responseJSON块在默认情况下在主队列中执行,因此通过调用waitUntilAllOperationsAreFinished来阻止主线程将阻止它完全执行完成块。

首先,为了解决死锁问题,您可以告诉Alamofire在不同的队列中执行完成块,其次,您可以使用dispatch_group_t对异步HTTP请求的数量进行分组并保留主线程等到小组中的所有请求都完成执行:

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")

答案 1 :(得分:2)

我建议您使用KVO并观察队列何时完成所有任务,而不是阻止当前线程直到所有操作完成。或者您可以使用依赖项。看看this SO问题

答案 2 :(得分:1)

要检查所有操作是否已完成-我们可以使用KVO观察队列中的操作数。不幸的是, operations operationCount 当前均已被弃用

因此使用依赖项的以下选项是安全的。

要检查一些操作是否已完成-使用依赖项:

创建一个名为“ finishOperation”的最终操作,然后将依赖项添加到所有其他必需的操作中。这样,仅当相关操作完成时才执行“ finishOperation”。检查此answer以获得代码示例。