道歉,我想不出一个更好的方法来标题。
基本上我有一个连接到Parse的应用程序。我已经指定了一个动作,它在文本字段被更改时运行(即当用户键入一个字母时)
在这个动作中我正在调用PFQuery来解析,然后我要求findObjectsInBackgroundWithBlock。
问题是,如果用户在此查询完成运行之前键入另一个字母,则现在正在运行2个查询,并且两个结果最终填充tableView。
所以我的问题很简单,如果用户在第一个findObjectsInBackgroundWithBlock完成之前输入另一个字母,我将如何取消第一个并运行一个新的?
我已尝试在操作开始时插入PFQuery.cancel(查询),但代码感到困惑,因为当该操作第一次运行时尚未运行查询。
我的代码,包含它可能会有所帮助:
@IBAction func textFieldChanged (sender: AnyObject) {
let query = PFUser.Query()
query!.whereKey("Postcode", containsString: searchField.text)
query?.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
for object in objects {
self.citiesArray.append(object["city"] as! String)
}
}
})
非常感谢您的耐心等待!
答案 0 :(得分:4)
您可以尝试在NSOperation
中包装这些请求,并将其添加到专用(针对此类搜索请求)NSOperationQueue
并在键入新字符时调用cancelAllOperations()
。
在NSOperation
的内部Parse块中检查self.cancelled
,如果取消则不返回任何内容。应该工作正常。
<强>更新强>:
class ViewController: UIViewController { @IBOutlet weak var searchField: UITextField! var citiesArray = [String]() lazy var textRequestQueue: NSOperationQueue = { var queue = NSOperationQueue() queue.maxConcurrentOperationCount = 1 queue.qualityOfService = NSQualityOfService.UserInteractive return queue }() @IBAction func textFieldChanged(sender: AnyObject) { textRequestQueue.cancelAllOperations() let query = PFQuery() query.whereKey("Postcode", containsString: searchField.text) textRequestQueue.addOperation(TextRequestOperation(query: query, resultBlock: { (objects, error) -> Void in if let objects = objects { for object in objects { self.citiesArray.append(object["city"] as! String) } } })) } } class TextRequestOperation: NSOperation { typealias ResultBlock = ((result: String)->()) var _resultBlock: PFArrayResultBlock var _query: PFQuery init(query: PFQuery, resultBlock: PFArrayResultBlock) { self._resultBlock = resultBlock self._query = query } override func main() { if self.cancelled { return } _query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in if self.cancelled { return } self._resultBlock(objects, error) } } }
答案 1 :(得分:2)
NSOperation
是一种选择。 ReativeCocoa
是另一个选项,可以帮助您轻松解决此问题,如果您知道如何使用它。
然而,最简单的方法(也是最黑客的)可能是保留一些搜索状态并使用它来仅应用最新的搜索结果。
var mostRecentSearchQuery: String = ""
@IBAction func textFieldChanged (sender: AnyObject) {
var queryString: String?
if let textField: UITextField = sender as? UITextField {
queryString = textField.text
self.mostRecentSearchQuery = textField.text
}
let query = PFUser.Query()
query!.whereKey("Postcode", containsString: searchField.text)
query?.findObjectsInBackgroundWithBlock({[weak self] (objects, error) -> Void in
if let objects = objects where queryString == self?.mostRecentSearchQuery {
for object in objects {
self.citiesArray.append(object["city"] as! String)
}
}
})
如果块使用了最近输入的文本,则只会更新结果。
PS。我假设传递给方法的发送者是textField,文本已经改变了。