How can I add a timer to my iOS app that is based on user interaction (or lack thereof)? In other words, if there is no user interaction for 2 minutes, I want to have the ap
Background [Swift Solution]
There was a request to update this answer with Swift so I've added a snippet below.
Do note that I have modified the specs somewhat for my own uses: I essentially want to do work if there are no UIEvents for 5 seconds. Any incoming touch UIEvent will cancel previous timers and restart with a new timer.
Differences from Answer Above
init() immediately. Also my reset_idle_timer() will cancel the previous timer so only one timer will be running at any time.IMPORTANT: 2 Steps Before Building
Thanks to a couple great answers on SO, I was able to adapt the code above as Swift code.
Follow this answer for a rundown on how to subclass UIApplication in Swift. Make sure you follow those steps for Swift or the snippet below won't compile. Since the linked answer described the steps so well, I will not repeat here. It should take you less than a minute to read and set it up properly.
I could not get NSTimer's cancelPreviousPerformRequestsWithTarget: to work, so I found this updated GCD solution which works great. Just drop that code into a separate .swift file and you are gtg (so you can call delay() and cancel_delay(), and use dispatch_cancelable_closure).
IMHO, the code below is simple enough for anyone to understand. I apologise in advance for not answering any questions on this answer (a bit flooded with work atm).
I just posted this answer to contribute back to SO what great information I've gotten out.
Snippet
import UIKit
import Foundation
private let g_secs = 5.0
class MYApplication: UIApplication
{
var idle_timer : dispatch_cancelable_closure?
override init()
{
super.init()
reset_idle_timer()
}
override func sendEvent( event: UIEvent )
{
super.sendEvent( event )
if let all_touches = event.allTouches() {
if ( all_touches.count > 0 ) {
let phase = (all_touches.anyObject() as UITouch).phase
if phase == UITouchPhase.Began {
reset_idle_timer()
}
}
}
}
private func reset_idle_timer()
{
cancel_delay( idle_timer )
idle_timer = delay( g_secs ) { self.idle_timer_exceeded() }
}
func idle_timer_exceeded()
{
println( "Ring ----------------------- Do some Idle Work!" )
reset_idle_timer()
}
}