我使用的是parse.com和Swift 2。
我需要在for循环中从parse中查找对象。问题是,findObjectsInBackgroundWithBlock是异步的,所以当query.findObjectsInBackgroundWithBlock中的闭包运行时,循环已经完成,迭代(i)的索引比opIdList.count大。所以我得到了数组索引超出范围的错误,因为opIdList、opUserIdlist和opLastIdChangedToList具有相同数量的元素。有没有我缺少的简单解决方案,或者我必须使用同步功能?(在本例中为findObjects())
for var i = 0; i < opIdList.count; ++i {
let query = PFQuery(className: "LastId")
query.whereKey("UserId", equalTo: opUserIdList[i])
query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if error == nil {
if objects?.count != 0 {
for object in objects! {
object.setValue(self.opLastIdChangedToList[i], forKey: "lastId")
object.saveInBackground()
processedOnes.append(i)
}
} else {
let item = PFObject(className: "LastId")
item["lastId"] = self.opLastIdChangedToList[i]
item["userId"] = self.opUserIdList[i]
item.saveInBackground()
processedOnes.append(i)
}
}
})
您可以使用递归而不是for循环。我不太理解你的代码中发生了什么,但我在下面的递归中实现了for循环的作用。
func reccursiveRquest(index:Int) {
let query = PFQuery(className: "LastId")
query.whereKey("UserId", equalTo: opUserIdList[index])
query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if error != nil {
if objects?.count != 0 {
for object in objects! {
object.setValue(self.opLastIdChangedToList[index], forKey: "lastId")
object.saveInBackground()
processedOnes.append(index)
}
if (index++) < opIdList.count { reccursiveRquest(index) }
} else {
let item = PFObject(className: "LastId")
item["lastId"] = self.opLastIdChangedToList[index]
item["userId"] = self.opUserIdList[index]
item.saveInBackground()
processedOnes.append(index)
if (index++) < opIdList.count { reccursiveRquest(index) }
}
}
})
}
正如您所说,正如名称findObjectsInBackgroundWithBlock
所暗示的,它在后台运行,因此是异步的。你不能用这种方式做你想做的事。
要么需要更改逻辑以允许异步任务完成,然后完成处理,要么需要同步运行查询(并确保不会不适当地阻塞当前线程,尤其是当该线程是主线程时)。
可以通过用NSNull
填充数组,然后在到达时替换每个项来完成前者。您将需要一些方法来检查是否所有操作都已完成,以便触发数组是否已准备好使用。
在某些方面,最好使其同步并在后台线程上运行整个过程,因为这也可以防止您同时向网络发出过多请求。然后,知道什么时候完成并且可以返回整个完成的数组也是很琐碎的。