我正在尝试从我的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线程,而且,当我从其他用户(内部异步请求)获取数据时,如果数据连接中断,它将失败并使应用程序崩溃,导致循环永远不会完成。
我的问题是如何使用完成处理程序返回它应该返回的所有数据,而不会阻塞主线程和/或不必担心数据连接丢失时间不合理。
答案 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
上的更新。