mike
mike

Reputation: 374

What is the "cleartimeout" equivalent for Swift?

I'm trying to set up a timeout on a text input field that only implements the inner code a second after the user stops typing. So while the user is typing, I would continually call a cleartimeout and re-initiate the setTimeout.

I was originally looking at the performSelector function in Objective C, but it looks like there is no Swift equivalent for this.

Then I moved on to the GCD functions in Swift, looking for a way to execute this.

Here is what I came up with:

var delta: Int64 = 1 * Int64(NSEC_PER_SEC)
var time = dispatch_time(DISPATCH_TIME_NOW, delta)
dispatch_suspend(dispatch_get_main_queue())
dispatch_after(time, dispatch_get_main_queue(), {
    println("timeout")
});

The dispatch_suspend function is not working as I was hoping.

Maybe the dispatch functions are not appropriate here?

Upvotes: 3

Views: 4038

Answers (1)

Rob
Rob

Reputation: 437622

You can use dispatch_after rather than one of the performSelector. But I don't think either of these is what you want.

If you are looking to call a block of code only after it's been idle for one second, then I think you want to use a timer (e.g. Timer is fine, or you could use a dispatch timer). Bottom line, every time you get keyboard interaction, see if there is a pending timer, and if so, invalidate it, and then schedule the new one.

So I might be inclined to do something like the following in Swift 3. For example, in iOS 10 and later, you can use the block rendition:

weak var timer: Timer?

func resetTimer() {
    timer?.invalidate()
    timer = .scheduledTimer(withTimeInterval: 1.0, repeats: false) { [weak self] timer in
        // do whatever you want when idle after certain period of time
    }
}

Or, if you need to support earlier iOS versions that do not have block-based timers:

weak var timer: Timer?

func resetTimer() {
    timer?.invalidate()
    timer = .scheduledTimer(timeInterval: 1, target: self, selector: #selector(handleIdleEvent(_:)), userInfo: nil, repeats: false)
}

@objc func handleIdleEvent(_ timer: Timer) {
    // do whatever you want when idle after certain period of time
}

If you use this latter approach, though, recognize that this Timer keeps a strong reference to its target, so you might want to cancel the timer in viewDidDisappear (but not deinit). This is why we prefer the block-based rendition or GCD timers.


By the way, I am not sure what your intent of dispatch_suspend was, but don't suspend the main queue. You never want to do anything that could potentially interfere with the main queue's timely processing of events (i.e., never block/suspend the main queue).

Upvotes: 8

Related Questions