如何在swift方法中等待异步竞争处理程序

时间:2015-12-22 13:09:33

标签: delegates swift2

我正在使用SwiftHttp进行网络API呼叫。我创建了一个通用的辅助方法来从Web Api获取数据并在完成处理程序中返回数据。这是代码。

public func getArray(let apiUri:String, let token:String, let parms:HTTPParameterProtocol? , completionHandler:(data:NSMutableArray?,error:NSError?)->Void) ->Void
{
    do {

        var header:[String:String]? = nil
        if token != ""{
            header = ["Authorization":"Bearer \(token)"]
        }

        let opt = try HTTP.GET(_baseurl + apiUri, parameters: parms, headers: header)

        opt.start { response in
            if let err = response.error {
                completionHandler(data:nil,error:err)                    
            }
            let data = response.data as NSData                
            do {
                if let mutableArray = try NSJSONSerialization.JSONObjectWithData(data, options:NSJSONReadingOptions.MutableContainers) as? NSMutableArray {

                    completionHandler(data:mutableArray, error:nil)
                }
            }
            catch let er as NSError{
                completionHandler(data:nil, error:er)
            }
        }
    } catch let error as NSError {
        completionHandler(data:nil,error:error)
    }

}

工作正常。

现在在我的调用方法中,我希望在单个方法中调用此方法5次(或更多次),并且该方法也有完成处理程序我想要这种方法'完成所有5个web api调用后,才会调用completionHalder。我是swift的新手

  public func loadAccountAndAuthorize(token:String, completionHander:(isLoaded:Bool,user:Account)->()){
   let myApi:WebApiHelper = WebApiHelper.WebApi
   myApi.getArray("User", token: token, parms: nil) { (data, error) -> Void in
        if error != nil {
            completionHander(isLoaded: false, user: Account())
        }
        else {
        }
      })
    myApi.getArray("secondAPi", token: token, parms: nil) { (data, error) -> Void in
        if error != nil {
            completionHander(isLoaded: false, user: Account())
        }
        else {
        }
      })

    myApi.getArray("thirdAPi", token: token, parms: nil) { (data, error) -> Void in
        if error != nil {
            completionHander(isLoaded: false, user: Account())
        }
        else {
        }
      })/// there can be more web api calls...


    //But This should be called when all web api calls are completed..
    completionHander(isLoaded: true, user: Account())
 }

1 个答案:

答案 0 :(得分:1)

该库中的HTTP类是来自NSOperationQueue的子类,因此最简单的解决方案是将所有这些操作放在队列中并创建一个新的NSBlockOperation,您也将其置于队列中但依赖于所有队列其他行动。

因此更改getArray()以在其Readme.md中使用操作队列示例并让它返回创建的操作。然后更改第二位代码以创建包含最终完成处理程序的块操作,并将getArray()中的每个返回操作作为依赖项添加,然后将其与所有其他操作放在同一队列中。

loadAccountAndAuthorize看起来像:

let completionOperation = NSBlockOperation {  
    completionHander(isLoaded: true, user: Account()) 
}

let op1 = myApi.getArray("User", token: token, parms: nil) { /* all the per request completion stuff */ })
completionOperation.addDependency(op1)
// Same for all the other operations

operationQueue.addOperation(completionOperation) // Will not run until all dependencies are complete.

如果你的最终完成块取决于所有其他的结果,你需要小心一点,因为所有这些现在都发生在不同的线程上,设置标志等可能会导致同步问题。使用GCD在主队列上的完成处理程序中分派工作可能是个好主意。事实上,如果他们进行UI更新,那将是强制性的。