1

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.

Community
  • 1
  • 1
Cue
  • 2,952
  • 3
  • 33
  • 54

1 Answers1

2

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)
    }
}
vadian
  • 274,689
  • 30
  • 353
  • 361
  • Thank you vadian, I implemented the method but i get this error "CoreAnimation: warning, deleted thread with uncommitted CATransaction; set CA_DEBUG_TRANSACTIONS=1 in environment to log backtraces." anyway now I'm checking whether I implemented in a wrong way. – Cue Mar 19 '17 at 12:18
  • 1
    Most likely `updateStatistics()` contains code to update the UI, so you need to dispatch the method to the main thread. I updated the answer. – vadian Mar 19 '17 at 12:35