2016-09-01 81 views
3

我有以下代碼:如何等待所有NSOperations完成?

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()不等待?

回答

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

我建議你使用KVO,並觀察隊列何時完成所有任務,而不是阻塞當前線程,直到所有操作完成。或者你可以使用依賴關係。看看this SO問題