views:

430

answers:

2

Hello all,

I have developed an application in which I'm running a countdown timer. The timer fires a method every second. However, when the phone is in sleep mode, the timer becomes slow or even turns off.

I think I need to update the variables by calculating the time intervals using NSDate. Does someone knows how to do this?

BTW, our client has sent the following feedback:

The timer problem appears to be caused by the fact that the code assumes that the timer notification messages are delivered at exactly one second, but aren't. When the app is running but the phone is in standby, it uses the timer to update the countdown timer. But the timer comes in way more slowly than one second, so the countdown timer is off. The app should be reworked to always update the countdown timer based on the current time, and not count down based on the timer messages themselves. (In other words, when the one second message comes in, always assume that additional time has gone by and calculate the remaining time by subtracting from the target time. This is what happens when you restart the app -- it figures out the target time and the current time, subtracts one from the other, and updates the onscreen timer. Well, this is how it should always do it.)

If someone understand what exactly we need, please tell me.

+1  A: 

Use epoch time. Epoch time is the number of seconds since Janury 1st, 1970.

When the program starts, save the current epoch time

double start = [[NSDate date] timeIntervalSince1970];

And then when you update your timer,

double running = [[NSDate date] timeIntervalSince1970] - start;

Will tell you how many seconds have passed since start.

Jeffrey Aylesworth
[NSDate date] _is_ the current time.
Graham Lee
Ah, thanks, I wasn't sure
Jeffrey Aylesworth
+1  A: 

NSTimers should never be used to actually keep time. They are dependent on the run loop and therefore can be interfered with by code that takes a long time to run.

You should stop the timer in applicationWillResignActive: and resume (actually, create another timer) in applicationDidBecomeActive:.

To calculate the dates you need something like:

    NSDate *startDate=[NSDate date];
    NSDate *endDate=[startDate addTimeInterval:someSeconds];
    NSTimeInterval secsElapsed;
    ...

-(void) timerDidFire:(NSTimer *) aTimer{
    NSDate *dateNow=[NSDate date];
    if ([[dateNow laterDate:endDate] isEqual:endDate]) {
        [aTimer invalidate];
        // end countdown
    }else {
        secsElapsed=[dateNow timeIntervalSinceDate:startDate];
    }
}
TechZen