【问题标题】:Delayed search in swift iOS appswift iOS应用程序中的延迟搜索
【发布时间】:2018-08-29 20:14:53
【问题描述】:

我有用于输入搜索字符串的 UITextField 和带有结果的 UITableView。 我想要的是当用户输入超过 3 个字母并且自最后一个符号添加到 UITextView 以来至少经过 0.5 秒时运行搜索功能。

我找到了 (Detect when user stopped / paused typing in Swift) 函数,并将它添加到我的 ViewController 中,它具有类 SearchVC 和方法 server_search

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    NSObject.cancelPreviousPerformRequests(
        withTarget: self,
        selector: #selector(SearchVC.server_search),
        object: textField)
    self.perform(
        #selector(SearchVC.server_search),
        with: textField,
        afterDelay: 0.5)
    return true
}

但是什么也没发生。

【问题讨论】:

  • 你为什么不使用计时器?

标签: ios swift


【解决方案1】:

您可以通过Timer 来实现这一点……

var timer: Timer?

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    timer?.invalidate()  // Cancel any previous timer

    // If the textField contains at least 3 characters…
    let currentText = textField.text ?? ""
    if (currentText as NSString).replacingCharacters(in: range, with: string).characters.count >= 3 {

         // …schedule a timer for 0.5 seconds
         timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(performSearch()), userInfo: nil, repeats: false)
    }

    return true
}

func performSearch() {

} 

并且不要忘记将视图控制器设置为您的UITextFielddelegate

【讨论】:

  • 使用 Swift 3,您实际上可以在计时器上使用完成块。这似乎使事情更容易使用和阅读。 :)
  • 感谢您“不要忘记将视图控制器设置为您的 UITextField 的代表” - 这是主要问题!
  • 快速修复:@objc func performSearch() { }
【解决方案2】:

虽然使用 Timer 仍然是一个有效的答案,但从 Swift 3 开始,您可以使用 DispatchWorkItem...

var workItem: DispatchWorkItem?

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    // Cancel any outstanding search
    self.workItem?.cancel() 

    guard let text = textField.text, let textRange = Range(range, in: text) else {
        return true
    }

    let updatedText = text.replacingCharacters(in: textRange, with: string)

    guard updatedText.count >= 3 else { 
        return true
    }

    // Set up a DispatchWorkItem to perform the search
    let workItem = DispatchWorkItem { [weak self] in
        self?.performSearch(updatedText)
    }

    // Run this block after 0.5 seconds
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: workItem)

    // Keep a reference to it so it can be cancelled
    self.workItem = workItem 

    return true   
}

func performSearch(_ text: String) {

} 

【讨论】:

    【解决方案3】:

    使用定时器有一些好处。通过您的实施,您将取消 您的对象的所有执行,这可能会失控。

    相反,计时器可以让您精细控制它。请参阅以下实现:

    var searchTimer: Timer?
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        // Invalidate remove the previous timer, since it's optional if the previous timer is already cancelled or nil, it won't affect execution
        searchTimer?.invalidate()
        searchTimer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false, block: { (timer) in
            //do Something crazy
            self.server_search()
        })
        return true
    }
    

    【讨论】:

    • 感谢您的回答 - 似乎很好,但我选择了 Ashley Mills 的答案是正确的,因为它有字符串长度检查并且不需要 iOS 10
    猜你喜欢
    • 2016-02-19
    • 2018-08-02
    • 1970-01-01
    • 2021-05-20
    • 1970-01-01
    • 1970-01-01
    • 2015-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多