边输入边搜索 Swift

Search as you type Swift

我尝试在您输入 Swift 时实现搜索。它已经工作了,但我需要一些调整。我发送每个输入

的字母
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {

    let debouncedFindUser = debounce(
        Static.searchDebounceInterval,
        Static.q,
        findUser)

    debouncedFindUser()
}

向后端请求。

func findUser() -> () {
    SearchService.sharedInstance.getUser(0, numberOfItems: 100,
        searchString: searchUserBar.text.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
        ,
        success: {SearchUserDto -> Void in
            if self.searchUserBar.text != nil {
                self.updateSearch()
            }
        },
        failure: {NSError -> Void in

    })
}

我尝试了在此处找到的 Debounce 实现 How can I debounce a method call?

我的问题:

我想 "restart" 在特定时间内触发的方法调用。所以让我们夸张一点。

只有在 2 秒内未输入搜索文本后才会启动请求。因此,如果我是一个快速打字员并且每 0.5 秒输入一个字母,那么除非我暂停至少 2 秒,否则永远不会触发请求。

您可以使用 NSTimer。在您的 textDidChange 中启动或使计时器失效并重新启动 2 秒。让计时器在实际弹出时触发 findUser 方法。

    var debounceTimer: NSTimer?

@IBAction func test() {
    if let timer = debounceTimer {
        timer.invalidate()
    }
    debounceTimer = NSTimer(timeInterval: 2.0, target: self, selector: Selector("getUser"), userInfo: nil, repeats: false)
    NSRunLoop.currentRunLoop().addTimer(debounceTimer!, forMode: "NSDefaultRunLoopMode")
}

func getUser() {
    println("yeah")
}

您遇到的问题是您在每次调用 findUser 函数之前都对其进行去抖动。您的去抖功能设置了初始计时器和延迟,但由于您每次都调用它,因此初始计时器始终为 "now"。您应该只去抖动一次,以便闭包可以保持其捕获的上次执行时间。

您只想调用 debounce 一次并将其存储为 属性,如下所示:

class MySearchController: ... {
    lazy var debouncedFindUser = debounce(
        Static.searchDebounceInterval,
        Static.q,
        self.findUser)

    ...

    func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
        debouncedFindUser()
    }

    func findUser() {
        ...
    }
}

你唯一需要做的就是创建一个定时器

  func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    let text = searchText.trimmingCharacters(in: .whitespacesAndNewlines)

// Create a Timer in this or parent class.
    debounceTimer.invalidate() // just in case this button is tapped multiple times


    // start the timer
    debounceTimer = Timer.scheduledTimer(timeInterval: 0.8, target: self, selector: #selector(self.startSearch(_:)), userInfo: text, repeats: false)
}

func startSearch(_ timer: Timer) {
    if let searchText = timer.userInfo as? String {
        print("Searching: \(searchText)")

        // make your service call here ...
    }
}