Reputation: 374
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
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