从for

时间:2015-06-10 20:43:20

标签: multithreading swift for-loop asynchronous

我正在尝试从我的RestAPI获取数据,特别是我得到一个整数数组(来自其他用户的id),我想循环遍历这个数组并从所有其他客户下载数据。代码的简化版本如下所示。

func asyncFunc(completion: (something:[Int])->Void){
  //Get a json Array asynchonous from my RestAPI
  let jsonArray = [1,2,3,4,5]

  var resultingArray:[Int] = []

  for myThing in jsonArray{
    anotherAsyncFunc(myThing, completion: { (somethingElse) -> Void in
      resultingArray.append(somethingElse)
    })
  }
}

func anotherAsyncFunc(data:Int, completion: (somethingElse:Int)->Void){
  //Get some more jsonData from RestApi/data
  let myLoadedData:Int = data*13356
  completion(somethingElse: myLoadedData)
}

如何让asyncFunc返回一个数组,其中包含从第二个(内部)异步请求中获取的所有项目。

我已经尝试从Rest Api获取首次请求的数组计数,并使用while循环“阻塞”UI线程,看看“new”数组是否收集了所有数据(计数是等于第一个请求数组的计数)。这有两个主要的缺点,主要是它阻止了UI线程,而且,当我从其他用户(内部异步请求)获取数据时,如果数据连接中断,它将失败并使应用程序崩溃,导致循环永远不会完成。

我的问题是如何使用完成处理程序返回它应该返回的所有数据,而不会阻塞主线程和/或不必担心数据连接丢失时间不合理。

1 个答案:

答案 0 :(得分:2)

您可以使用调度组通知。因此,创建一个调度组,为数组中的每个项输入组,在anotherAsyncFunc异步进程的完成处理程序中退出,然后创建一个通知,在所有的时候触发最终的completion闭包dispatch_group_enter来电已被相应的dispatch_group_leave电话抵消:

func asyncFunc(completion: (something:[Int])->Void){
    //Get a json Array asynchonous from my RestAPI
    let jsonArray = [1,2,3,4,5]

    var resultingArray:[Int] = []

    let group = dispatch_group_create()

    for myThing in jsonArray {
        dispatch_group_enter(group)
        anotherAsyncFunc(myThing) { somethingElse in
            resultingArray.append(somethingElse)
            dispatch_group_leave(group)
        }
    }

    dispatch_group_notify(group, dispatch_get_main_queue()) {
        completion(something: resultingArray)
    }
}

注意,您需要确保将更新同步到resultingArray正在执行的anotherAsyncFunc。最简单的方法是确保将其更新发送回主队列(如果您的REST API尚未执行此操作)。

func anotherAsyncFunc(data:Int, completion: (somethingElse:Int)->Void){
    //Get some more jsonData from RestApi/data asynchronously
    let myLoadedData:Int = data*13356
    dispatch_async(dispatch_get_main_queue()) {
        completion(somethingElse: myLoadedData)
    }
}

这只是一个例子。您可以使用所需的任何同步机制,但请确保相应地同步resultingArray上的更新。