这是执行异步块的一个基本问题,我还没有找到一个好的解决方案。
以下代码有效,但它会阻止主线程,我想避免这种情况。
override func shouldPerformSegueWithIdentifier(identifier: String?, sender: AnyObject?) -> Bool {
//check if transaction already exists
let trans = PFQuery(className: "Transactions")
trans.whereKey("itemId", equalTo: self.pfObject.objectId!)
//I need the count of objects in the query before I can proceed, but I don't want to block the main thread
let count = trans.countObjects()
if(count > 0){
return false
}else{
return true
}
}
此问题并非特定于我的应用程序的这一部分。通常,我可以在query.countObjectsInBackGroundWithBlock()之类的闭包中设置“count”(或者我需要的任何变量),但是当我需要在主线程上返回一些东西时我不能这样做。
是否有解决方案让我的应用程序等待返回而不阻塞主线程?我实际上并不认为在这种情况下没有重新设计大部分代码,但我只是想确保我不是天真的。
对于这些类型的问题,有哪些可接受的解决方案?
答案 0 :(得分:5)
对此的正确解决方案是不要从shouldPerformSegueWithIdentifier
调用任何不能很快完成的任何内容(在几毫秒内)。如果您需要执行一些可能需要几秒钟的网络请求,您应该:
退休shouldPerformSegueWithIdentifier
;
从您的UI控件中移除segue到下一个场景;
相反,将按钮连接到@IBAction
,它将以编程方式执行异步请求,并且只有在获得预期结果时,才能以编程方式手动执行segue(请参阅Switching Views Programmatically in Swift)
答案 1 :(得分:0)
编辑:这基本上是Rob的更多角色的答案
罗布的答案非常好。另一种方法,如果这是不好的做法,请告诉我,是调用self.performSegueWithIdentifier
(我希望我的方法名称正确,来自countObjectsInBackgroundWithBlock的完成块(或者,正如danh指出的那样,Parse阻止计数)查询,使用其他东西,也许是findObjectsInBackgroundWithBlock并计算[AnyObject]?数组。)
//IBAction method
func buttonFunc() {
let query = PFQuery(classname: "ClassName")
query.whereKey(itemId, equalTo: self.pfObject.objectId!)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
//maybe do some error checking etc.
if objects.count > 1 {
performSegueWithIdentifier(theParametersAndStuff)
}
}
}
如果需要将对象传递给下一个ViewController,则可以准备ForSegue,因为只有在buttonFunc
的完成块中的条件返回true时才会调用它。
(正如我所说,如果有人认为这是不好的做法,请告诉我为什么,我是古玩:))
编辑:当然你可以放一个活动指标或类似的。另一种方法是在显示当前viewController之前预先加载该数据,以启用或禁用触发segue的按钮(如danh指出的那样)。