2017-03-31 39 views
0

如何同步閉包?如何同步閉包?

我有這樣的代碼:??

private func getWeather(parameters: [String : Any], failure: ((String) -> Void)? = nil ,completion: (() -> Void)? = nil) { 

     for _ in 0...10 { 

      RequestManager.sharedInstance.request(url: baseURL, parameters: parameters, completion: { (result) in 
       if JSON.parse(result)["name"].string == nil { 
        failure?("Something went wrong. Please, try again later") 
       } else { 
        let weatherModel: WeatherModel = WeatherModel(json: JSON.parse(result)) 
       } 
      }) 
     } 
     completion?() 

    } 

在我的代碼,完成()將調用,而不是在所有的請求都將結束 我需要調用完成()時,所有的請求都將結束。何我能做到嗎?

+2

Research'DispatchGroup'。 – rmaddy

+0

[這裏是一個很好的教程](https://dispatchswift.com/introduction-to-dispatch-group-a5cf9d61ff4f) –

+0

或者看看nsoperation(隊列)和設置依賴關係 – vikingosegundo

回答

5

由於當前接受的答案不正確,因此以下是正確使用DispatchGroup的版本。

private func getWeather(parameters: [String : Any], failure: ((String) -> Void)? = nil ,completion: (() -> Void)? = nil) { 
    let dispatchGroup = DispatchGroup() 
    for _ in 0...10 { 
     dispatchGroup.enter() 
     RequestManager.sharedInstance.request(url: baseURL, parameters: parameters) { result in 
      if JSON.parse(result)["name"].string == nil { 
       failure?("Something went wrong. Please, try again later") 
      } else { 
       let weatherModel: WeatherModel = WeatherModel(json: JSON.parse(result)) 
      } 
      dispatchGroup.leave() 
     } 
    } 

    dispatchGroup.notify(queue: DispatchQueue.main) { 
     completion?() 
    } 
} 
+0

謝謝。我將開始使用這個,並刪除我接受的答案...或者我不能刪除一個被接受的答案... – Sethmr

+0

哦,@rmaddy,非常感謝您的幫助! – Banck

+0

@rmaddy如果你想貢獻,我做了一個關於該場景的meta post。 https://meta.stackoverflow.com/questions/346284/why-cant-i-delete-an-accepted-answer-posted-by-myself – Sethmr

0

一個簡單的方法來做到這一點只是計算完成的電話。

private func getWeather(parameters: [String : Any], failure: ((String) -> Void)? = nil ,completion: (() -> Void)? = nil) { 
    let numCalls = 11; 
    var completedCalls = 0; 

    for _ in 0..<numCalls { 

     RequestManager.sharedInstance.request(url: baseURL, parameters: parameters, completion: { (result) in 
      if JSON.parse(result)["name"].string == nil { 
       failure?("Something went wrong. Please, try again later") 
      } else { 
       let weatherModel: WeatherModel = WeatherModel(json: JSON.parse(result)) 
      } 
      completedCalls += 1 
      if completedCalls == numCalls { 
       completion?() 
      } 
     }) 
    } 
} 

當每個請求結束時,您的完成回調會運行。讓每個完成回調函數更新其封閉範圍中的值可以讓您跟蹤有多少請求已結束。當您預期的所有請求都已結束時,請致電completion?()

+0

是的,這是顯而易見的))但我認爲有一些優雅的解決方案:-) – Banck

+0

你可以嘗試創建一個函數,它抽象這個調用計數模式。這將需要做出什麼請求,做多少次或請求列表。 –

+0

我肯定會推薦使用DispatchGroup。 – Sethmr