2015-06-10 34 views
1

我想从我的RestAPI获取数据,特别是我得到一个整数数组(这是其他用户的ID),我想循环这个数组并下载数据来自所有其他客户。代码的简化版本如下所示。返回for循环中的异步请求

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它已经从第二(内)异步请求得到的所有物品返回数组。

我已经尝试获得第一个从其他Api请求的数组的计数,并通过使用while循环仅“阻塞”UI线程也看到“新”数组已收集所有数据(计数等于第一个请求数组的数量)。这有两个主要的缺点,主要是它阻塞了UI线程,更进一步说,它会失败,并在应用程序崩溃时,如果数据连接在我从其他用户(内部异步请求)获取数据时断开,导致循环永远不会完成。

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

回答

2

您可以使用调度组通知。因此,创建一个调度组,为数组中的每个项目输入组,退出anotherAsyncFunc异步过程的完成处理程序,然后创建一个通知,当所有dispatch_group_enter调用已被偏移量为1时,将触发最终的completion关闭。相应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) 
    } 
} 

注意,你将要确保你的anotherAsyncFunc正在执行的同步更新到resultingArray。最简单的方法是确保它将更新发送回主队列(如果您的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上的更新。

+0

谢谢,永远不知道这个功能。像魅力一样工作!这将如何处理在下载时丢失数据连接? – milo526

+0

在Swift 1.2中,你通常会在anotherAsyncFunc的'completion'块参数中添加一个可选的错误参数,并使'somethingElse'成为一个可选参数,并且确保调用'completion'块是否成功(设置错误或酌情引用“somethingElse”)。 – Rob