我有一个loadItem函数,可以从解析服务器加载项目。这包括一个循环,其中我在最后将数据保存到数组:
itemArray?.addObject(arrayDic)
当保存时,我想重新加载collectionView的数据。因此我已经将它插入到dispatch_async块中,但是在将数据保存到itemArray数组之前它似乎仍在运行,因为itemArray.count为0并且我在循环内检查了数据保存到数组中。我究竟做错了什么?
func loadItems() {
var query = PFQuery(className:"Items")
query.orderByAscending("createdAt")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
for object in objects {
var imageRelation: PFRelation = object.relationForKey("pictures")
var query = imageRelation.query()
query.orderByDescending("createdAt")
query.findObjectsInBackgroundWithBlock {
(imageObjects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
var theArray = imageObjects as NSArray
var arrayDic = NSMutableDictionary()
let imageFile = theArray.objectAtIndex(0).objectForKey("image") as PFFile
imageFile.getDataInBackgroundWithBlock {
(imageData: NSData!, error: NSError!) -> Void in
if !(error != nil) {
let image = UIImage(data:imageData)
arrayDic.setValue(object.objectForKey("price"), forKey: "price")
arrayDic.setValue(image, forKey: "image")
itemArray?.addObject(arrayDic)
}
}
}
}
}
dispatch_async(dispatch_get_main_queue()) {
println(itemArray?.count)
self.collectionView.reloadData()
}
} else {
// Log details of the failure
NSLog("Error: %@ %@", error, error.userInfo!)
}
}
}
答案 0 :(得分:0)
我不建议尝试使请求同步(因为这会显着减慢进程,除非您安排它们在某些并发后台队列上并发运行)。相反,我会建议一种模式,允许您保留异步请求,但会通知您它们的完成情况。一个这样的模式是调度组,您可以在其中:
创建一个调度组:
let group = dispatch_group_create()
对于循环的每次迭代,请调用dispatch_group_enter
:
dispatch_group_enter(group)
赢取异步方法的完成块,调用dispatch_group_leave
:
dispatch_group_leave(group)
指定调度组完成时您要执行的操作:
dispatch_group_notify(group, dispatch_get_main_queue()) {
println(self.itemArray?.count)
self.collectionView.reloadData()
}
当dispatch_group_enter
的所有电话都被最后的dispatch_group_leave
电话抵消时,系统会为您调用通知屏。
因此,在遍历对象时查看代码,它可能看起来像:
let group = dispatch_group_create()
for object in objects {
dispatch_group_enter(group)
// do some stuff
query.findObjectsInBackgroundWithBlock {
(imageObjects: [PFObject]!, error: NSError!) -> Void in
if error == nil {
// do some more stuff
imageFile.getDataInBackgroundWithBlock {
(imageData: NSData!, error: NSError!) -> Void in
if !(error != nil) {
// do even some more stuff
}
dispatch_group_leave(group)
}
} else {
dispatch_group_leave(group)
}
}
}
dispatch_group_notify(group, dispatch_get_main_queue()) {
println(self.itemArray?.count)
self.collectionView.reloadData()
}
它们是其他功能上等效的模式(例如,使用屏障调度的最终reloadData
的自定义并发调度队列;将这些单独的请求NSOperation
对象添加到NSOperationQueue
并创建单独的完成操作依赖于那些其他操作;等等),但调度组似乎需要对此代码进行最少的重构。无论如何,希望这说明了基本思想:只有在完成其他异步请求时才会触发最终重新加载。