2016-09-01 14 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質問

関連する問題