In my app I have a NSTimer, and a selector - (void)TimerCount
. I also have a integer int CountNum
, and every 0.01 second, it increases by 1 (CountNum = CountNum + 1
).
Timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(TimerCount) userInfo:nil repeats:YES];
And I want the timer to resume thought the app is terminated or it entered background. How can I do this?
If your application is terminated, you will not be able to continue processing. To operate in the background, there are such things as background tasks, but it sounds like your use case does not warrant them. Because your incrementing is linear and computable, you could assign your start date to NSUserDefaults
, then load it back when your application resumes and update your count.
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]] forKey:@"start_time"];
NSNumber *start = [[NSUserDefaults standardUserDefaults] objectForKey:@"start_time"];
countNum = ceil([[NSDate date] timeIntervalSince1970] * 100) - ceil([start doubleValue] * 100);
A couple of thoughts:
Generally you wouldn't try to keep the timer going. You should avoid having the app doing anything in the background if you don't need to. You're unnecessarily draining the user's system resources (battery, memory, CPU cycles, etc.).
If you need to get the user's attention at time point of time in the future when the app might not be running (e.g. if this was a count-down or alarm-like function you're implementing), use location notification rather than using timer.
Also, if you're trying to keep track of how much time has elapsed, using NSTimer
is not the right solution (especially if you're firing it off 100 times per second). Capture the start time and then when you want to identify how much time has elapsed, then at any future point in time, you can grab the current time and compare it to the start time.
The beauty of this approach is that you no longer care about the frequency that you do this process. If you're updating the UI, you can call this 60 times per second. If the app is in the background, you don't have to do anything until the app is brought back into the foreground (just save the start time in persistent storage, such as NSUserDefaults
and then retrieve it again when the app starts up again).
Bottom line, by moving away from the "counter" approach to a "compare current time to start time" approach, you decouple the UI from the timer. Needless to say, once you've done that, you don't need the timer at all when the app leaves the foreground.
If you absolutely need the timer to run when the app leaves foreground, there are ways to do that (e.g. request a few minutes to complete some finite length task), but only do that if you absolutely need to. If you're only updating a counter, then you definitely don't want to do that.
You can use NSuserdefaults to save your countNum, whenever user will quit the app it will be saved. Just call this into APPDELEGATE function - (void)applicationWillTerminate:(UIApplication *)application {
NSUserDefault *defaults = [NSUser Defaults standardUserDefaults];
[defaults setInteger: countNum forKeys:@"ANY_KEY_HERE"];
[defaults synchronise];
the above code will save your countNum, but you have to save it when user will terminate or go into background.
And When User will come into foreground you can call to retrive your countNum
NSUserDefault *defaults = [NSUser Defaults standardUserDefaults];
yourCountNum = [default getIntegerForKeys: @"ANY_KEY_HERE"];