I'm going to describe my scenario:
I have a UIViewController
that is always loaded whenever a user signs in the app because it manages an UIView
that is always shown once the user is logged in. This UIView
disappears when the user logs out. This UIViewController
has a @property (strong, nonatomic) NSTimer *timer;
declared. I want this timer to show the user a countdown that may take several minutes long. This timer should start whenever the UIView
is shown and restarts its counting for every 20 secs in order to refresh the countdown displayed each 20 secs until it reaches 0:
-(void)start
{
if (self.timer != nil) {
[self.timer invalidate];
self.timer = nil;
}
// Some operations here
self.countdown = untilTime; // countdown total secs
self.timer = [NSTimer scheduledTimerWithTimeInterval:20
target:self
selector:@selector(notifyTimerTick:)
userInfo:nil
repeats:YES];
}
- (void)notifyTimerTick:(NSTimer *)timer
{
self.countdown -= 20;
if (self.countdown <= 0) {
[self start];
}
[self updateCountdown]; // Countdown label shown to user
}
That is, whenever the countdown reaches 0, a new countdown starts again for N minutes depending on certain operations I perform in -(void)start
method. And this scenario should keep working as long as the user is logged in the app.
In AppDelegate
, I stop this timer when the app becomes inactive or goes to background (or user logs out):
- (void)applicationWillResignActive:(UIApplication *)application
{
if (isUserLogged) {
[self.countdownViewController stopTimer];
}
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
if (isUserLogged) {
[self.countdownViewController stopTimer];
}
}
Where stopTimer
method is this:
- (void)stopTimer
{
if (self.timer != nil) {
[self.timer invalidate];
self.timer = nil;
}
}
I start again the timer in applicationDidBecomeActive:
method by calling -(void)start
method I already described, method that I also call when the user logs in the app.
This is working for me the 95% of times, but I've found in a couple of times during testing that sometimes the countdown goes faster than it should. I mean, for example: if countdown should take 6 min, it took more or less 3 min to reach the 0 value the last time I saw this weird effect, and the countdown shown to user was updating faster as well. It was like there were more than one timer performing the countdown, but I don't understand why, because it is usually working fine and I don't find what circumstances are causing this.
I found this fast countdown while testing a beta version of the app in a real iOS 7 device. When I wanted to see what was happening, and I connected the device to Xcode
and Instruments
, the app launching caused the timer working fine again, so I couldn't debug nor see anything in 'Instruments' of this scenario.
I think I'm managing the timer correctly, am I missing something? Has somebody experienced something like this? I've read some posts about releasing timers, but they only say that you have to invalidate the timer and I'm already doing it:
Correct way to release NSTimer?
I need help to analyze this issue. Thanks a lot in advance
EDIT: Does my code ensure that only one NSTimer
object can be running? Should I manage something related to the timer in dealloc
method?