I was able to adapt Sven Tan's answer to my existing code in Swift. In my case, I am sending the string to a method that loads the search results async. Additionally, I am not using the UISearchBar but rather a plain old UITextField.
var currentTempQuery = ""
...
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
if let t = textField.text {
let s: NSString = t
let newString = s.stringByReplacingCharactersInRange(range, withString: string).trim()
NSObject.cancelPreviousPerformRequestsWithTarget(self, selector:#selector(MyViewController.sendSearchRequest(_:)), object: currentTermQuery)
// Don't replace currentTermQuery until after the cancelPreviousPerformRequestWithTarget call
currentTermQuery = newString
performSelector(#selector(MyViewController.sendSearchRequest(_:)), withObject: newString, afterDelay: 1)
}
return true
}
Here is the selector that is being called:
func sendSearchRequest(text: String?) {
// Call async search method here...
}
The way that cancelPreviousPerformRequestsWithTarget
works is you need to pass the same target, selector, and object that was passed in the performSelector
call in order for the previous request to be cancelled. In my implementation, since I am passing just a string, I need to preserve the current request string between calls so I can reference it to cancel requests.
The result works for typing and deleting characters into my UITextField. Only one search is sent per major search term change.
Like I said, similar to what Sven Tan posted but slightly different usage. Hopefully this helps some people out.