UPDATE 2016/09/01:
We can use NSTimers
or (since swift 2.0) NSObject's performSelector
and friends.
Aproach 1 : performSelector
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
NSObject.cancelPreviousPerformRequests(
withTarget: self,
selector: #selector(ViewController.getHintsFromTextField),
object: textField)
self.perform(
#selector(ViewController.getHintsFromTextField),
with: textField,
afterDelay: 0.5)
return true
}
func getHintsFromTextField(textField: UITextField) {
print("Hints for textField: \(textField)")
}
Approach 2: NSTimer
var timer: NSTimer? = nil
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
timer?.invalidate()
timer = Timer.scheduledTimer(
timeInterval: 0.5,
target: self,
selector: #selector(ViewController.getHints),
userInfo: ["textField": textField],
repeats: false)
return true
}
func getHints(timer: Timer) {
var userInfo = timer.userInfo as! [String: UITextField]
print("Hints for textField: \(userInfo["textField"])")
}
Note I am passing the textField
to delayed functions. It is not always required but it could make your life easier when textField
is not easy to access or when dealing with various text fields.
How NSTimer
approach is different from performSelector
?
When you call performSelector
the target is retained (in swift the target is always self
) but when you use NSTimer
the target is NOT retained. This means, if you use NSTimer
s, you have to make sure target (in this case self
) is alive by the time the timer fires. Otherwise the a crash will occur.
(BTW: performSelector
uses NSTimer
internally )
If you are interested in GCD timers this gist a good place start:
maicki/TimerWithGCD.md