I have UITextField for entering search string and UITableView with results. What i want is to run search function when user entered more than 3 letters and it at least 0,5 sec passed since last symbol added to UITextView.
I found (Detect when user stopped / paused typing in Swift) function and I added it to my ViewController that have class SearchVC and method 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
}
But nothing happens.
While using a Timer
is still a valid answer, since Swift 3, you can use a 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) {
}
The use of Timers have some advantages. With your implementation you would cancel all the performs in for your object, which is something that may go out of control.
A Timer, instead, lets you fine grain control it. See the following implementation:
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With