2016-09-01 2 views
3

나는 다음과 같은 코드가 있습니다모든 NSOperations가 끝날 때까지 기다리는 방법?

finished 
i = 3 
i = 1 
i = 2 

그러나 나는 다음과 같은 기대 :

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

출력은

i = 3 
i = 1 
i = 2 
finished 

을 그럼, 왜 queue.waitUntilAllOperationsAreFinished()하지 않습니다 기다림?

답변

5

Alamofire.request이 응답 데이터를 기다리지 않고 단순히 반환하기 때문에 대기열에 추가 한 각 작업이 즉시 실행됩니다.

또한 교착 상태가 발생할 수 있습니다. responseJSON 블록은 기본적으로 기본 큐에서 실행되므로 waitUntilAllOperationsAreFinished을 호출하여 주 스레드를 차단하면 완료 블록을 전혀 실행하지 못하게됩니다.

첫째, 교착 상태 문제를 해결하기 위해, 당신은 두 번째, 당신이 그룹에 비동기 HTTP 요청의 수를 dispatch_group_t을 사용할 수 있습니다, 다른 큐에 완료 블록을 실행하고 모든 때까지 기다리는 메인 스레드를 유지하기 위해 Alamofire 말할 수

그룹의 요청이 실행을 마칩니다.

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에 대한 질문