Reputation: 3092
I need to perform a particular method (updateStatistics) when user don't type in a particular NSTextView for 2 seconds. I need this because when the text is particularly large, the updateStatistics method can cause delays in typing.
Maybe I could store the time where user ends to digit in textDidChange():
func textDidChange(_ notification: Notification) {
startDate = Date()
Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(self.updateStatistics), userInfo: nil, repeats: false)
}
And then learn if 2 seconds are elapsed in the updateStatistics method:
func updateStatistics() {
let currentDate = Date()
let elapsed = currentDate.timeIntervalSince(startDate)
if elapsed >= 2 {
// update statistics code
}
}
PS There is already an answer to a somewhat similar question here, but it's for iOS and Objective-C.
Upvotes: 1
Views: 680
Reputation: 285150
You need a timeout timer which can be restarted when the user presses a key.
Call this method in textDidChange
. It creates a timeout timer (once) and restarts it until the timer fires. When the timer fires it will be invalidated and you can execute your statistics code. When a key is pressed the cycle will begin again. The GCD DispatchSourceTimer
is perfect for this purpose because unlike (NS)Timer
it can be restarted.
var timeoutTimer : DispatchSourceTimer!
func startTimer()
{
let delay : DispatchTime = .now() + .seconds(2)
if timeoutTimer == nil {
timeoutTimer = DispatchSource.makeTimerSource()
timeoutTimer.scheduleRepeating(deadline: delay, interval: 0)
timeoutTimer.setEventHandler {
timeoutTimer.cancel()
timeoutTimer = nil
DispatchQueue.main.async {
// do something after time out on the main thread
self.updateStatistics()
}
}
timeoutTimer.resume()
} else {
timeoutTimer.scheduleRepeating(deadline: delay, interval: 0)
}
}
Upvotes: 2