Has anybody implemented a feature where if the user has not touched the screen for a certain time period, you take a certain action? I'm trying to figure out the best way to do that.
There's this somewhat-related method in UIApplication:
[UIApplication sharedApplication].idleTimerDisabled;
It'd be nice if you instead had something like this:
NSTimeInterval timeElapsed = [UIApplication sharedApplication].idleTimeElapsed;
Then I could set up a timer and periodically check this value, and take some action when it exceeds a threshold.
Hopefully that explains what I'm looking for. Has anyone tackled this issue already, or have any thoughts on how you would do it? Thanks.
This thread was a great help, and I wrapped it up into a UIWindow subclass that sends out notifications. I chose notifications to make it a real loose coupling, but you can add a delegate easily enough.
Here's the gist:
http://gist.github.com/365998
Also, the reason for the UIApplication subclass issue is that the NIB is setup to then create 2 UIApplication objects since it contains the application and the delegate. UIWindow subclass works great though.
I have a variation of the idle timer solution which doesn't require subclassing UIApplication. It works on a specific UIViewController subclass, so is useful if you only have one view controller (like an interactive app or game may have) or only want to handle idle timeout in a specific view controller.
It also does not re-create the NSTimer object every time the idle timer is reset. It only creates a new one if the timer fires.
Your code can call
resetIdleTimer
for any other events that may need to invalidate the idle timer (such as significant accelerometer input).(memory cleanup code excluded for brevity.)
I just ran into this problem with a game that is controlled by motions i.e. has screen lock disabled but should enable it again when in menu mode. Instead of a timer I encapsulated all calls to
setIdleTimerDisabled
within a small class providing the following methods:disableIdleTimer
deactivates idle timer,enableIdleTimerDelayed
when entering the menu or whatever should run with idle timer active andenableIdleTimer
is called from your AppDelegate'sapplicationWillResignActive
method to ensure all your changes are reset properly to the system default behaviour.I wrote an article and provided the code for the singleton class IdleTimerManager Idle Timer Handling in iPhone Games
Here's the answer I had been looking for:
Have your application delegate subclass UIApplication. In the implementation file, override the sendEvent: method like so:
where maxIdleTime and idleTimer are instance variables.
In order for this to work, you also need to modify your main.m to tell UIApplicationMain to use your delegate class (in this example, AppDelegate) as the principal class:
There's a way to do this app wide without individual controllers having to do anything. Just add a gesture recognizer that doesn't cancel touches. This way, all touches will be tracked for the timer, and other touches and gestures aren't affected at all so no one else has to know about it.
In your app delegate's did finish launch method, just call addGesture and you're all set. All touches will go through the CatchAllGesture's methods without it preventing the functionality of others.
Ultimately you need to define what you consider to be idle - is idle the result of the user not touching the screen or is it the state of the system if no computing resources are being used? It is possible, in many applications, for the user to be doing something even if not actively interacting with the device through the touch screen. While the user is probably familiar with the concept of the device going to sleep and the notice that it will happen via screen dimming, it is not necessarily the case that they'll expect something to happen if they are idle - you need to be careful about what you would do. But going back to the original statement - if you consider the 1st case to be your definition, there is no really easy way to do this. You'd need to receive each touch event, passing it along on the responder chain as needed while noting the time it was received. That will give you some basis for making the idle calculation. If you consider the second case to be your definition, you can play with an NSPostWhenIdle notification to try and perform your logic at that time.