【问题标题】:Swift: How to cancel a PFQuery if function is run again before PFQuery is finished?Swift:如果在 PFQuery 完成之前再次运行函数,如何取消 PFQuery?
【发布时间】:2015-08-03 13:42:07
【问题描述】:

抱歉,我想不出一个更好的标题。

基本上我有一个连接到 Parse 的应用程序。我指定了一个动作,它在文本字段更改时运行(即当用户键入字母时)

在此操作中,我调用 PFQuery 来解析,然后我要求 findObjectsInBackgroundWithBlock。

问题在于,如果用户在此查询完成运行之前键入另一个字母,那么现在有 2 个查询正在运行,并且两个查询的结果最终都会填充 tableView。

所以我的问题很简单,如果用户在第一个 findObjectsInBackgroundWithBlock 完成之前输入另一个字母,我将如何取消第一个并运行一个新的?

我尝试在操作开始时插入 PFQuery.cancel(query),但代码会混淆,因为当操作第一次运行时还没有运行查询。

我的代码,以防万一:

@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)
      }
   }
})

非常感谢您的耐心等待!

【问题讨论】:

    标签: ios swift parse-platform pfquery


    【解决方案1】:

    您可以尝试将这些请求包装在 NSOperation 中,并将它们添加到专用(用于此类搜索请求)NSOperationQueue,并在输入新字符时调用 cancelAllOperations()

    NSOperation 的内部Parse 块中检查self.cancelled,如果取消则什么也不做。应该可以正常工作。

    更新

    类视图控制器:UIViewController { @IBOutlet 弱 var searchField:UITextField! var cityArray = [字符串]() 懒惰的 var textRequestQueue: NSOperationQueue = { var queue = NSOperationQueue() queue.maxConcurrentOperationCount = 1 queue.qualityOfService = NSQualityOfService.UserInteractive 返回队列 }() @IBAction func textFieldChanged(sender: AnyObject) { textRequestQueue.cancelAllOperations() 让查询 = PFQuery() query.whereKey("邮政编码", containsString: searchField.text) textRequestQueue.addOperation(TextRequestOperation(query: query, resultBlock: { (objects, error) -> Void in 如果让对象=对象{ 对象中的对象{ self.citiesArray.append(object["city"] as!String) } } })) } } 类TextRequestOperation:NSOperation { typealias ResultBlock = ((result: String)->()) var _resultBlock: PFArrayResultBlock var _query: PFQuery 初始化(查询:PFQuery,结果块:PFArrayResultBlock){ self._resultBlock = 结果块 self._query = 查询 } 覆盖 func main() { 如果 self.cancelled { return } _query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in 如果 self.cancelled { return } self._resultBlock(对象,错误) } } }

    【讨论】:

    • 谢谢,我已经研究过 NSOperations,但由于我对编程很陌生,所以我感到很困惑。你介意用代码告诉我我将如何去做吗?非常感谢
    【解决方案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。我假设传递给方法的发件人是文本已更改的文本字段。

    【讨论】:

    • 太棒了,我感激不尽。这是我最终采用的方法,因为它是最简单的,尽管我非常感谢 rshev 编写的代码
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-04
    • 1970-01-01
    相关资源
    最近更新 更多