Here is my situation: I am making a countdown app which works fine but does not appear to stop when I call [stopWatchTimer invalidate];, and I have no idea why. Here is my code:
- (IBAction)btnStartPressed:(id)sender {
//Start countdown with the time on the Date Picker.
timeLeft = [pkrTime countDownDuration];
[self currentCount];
lblTimer.text = time; //sets the label to the time set above
pkrTime.hidden = YES;
btnStart.hidden = YES;
btnStop.hidden = NO;
//Fire this timer every second.
stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/1.0
target:self
selector:@selector(reduceTimeLeft:)
userInfo:nil
repeats:YES];
}
- (void)reduceTimeLeft:(NSTimer *)timer {
//Countown timeleft by a second each time this function is called
timeLeft--;
// Get the system calendar
NSCalendar *sysCalendar = [NSCalendar currentCalendar];
// Create the NSDates
NSDate *date1 = [[NSDate alloc] init];
NSDate *date2 = [[NSDate alloc] initWithTimeInterval:timeLeft sinceDate:date1];
// Get conversion to months, days, hours, minutes
unsigned int unitFlags = NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents *conversionInfo = [sysCalendar components:unitFlags fromDate:date1 toDate:date2 options:0];
int sec = [conversionInfo second];
int min = [conversionInfo minute];
int hour = [conversionInfo hour];
NSString *seconds = [NSString stringWithFormat:@"%d",sec];
NSString *minutes = [NSString stringWithFormat:@"%d",min];
if (sec <= 9)
seconds = [NSString stringWithFormat:@"0%d", sec];
if (min <= 9)
minutes = [NSString stringWithFormat:@"0%d", min];
if ([conversionInfo hour] == 0)
time = [NSString stringWithFormat:@"%@:%@", minutes, seconds];
else
time = [NSString stringWithFormat:@"%d:%@:%@", hour, minutes, seconds];
lblTimer.text = time; //sets the label to the time set above
NSLog(@"%d", timeLeft);
if (timeLeft == 0) {
[self timerDone];
[stopWatchTimer invalidate];
stopWatchTimer = nil;
}
}
-(void)timerDone {
pkrTime.hidden = NO;
btnStart.hidden = NO;
btnStop.hidden = YES;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Timer Done" message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:@"Ok", nil];
[alert show];
[self playAlert];
}
Please let me know what the problem is… I cannot find a problem with my code anywhere!
In your
btnStartPressed:method, you have nothing preventing a secondNSTimerfrom being allocated and assigned tostopWatchTimer. If you press the button twice, you’ll end up with two timers, but only one will ever be invalidated.Add something like:
To the beginning of
btnStartPressed:. If that doesn’t fix the problem, then there isn’t enough context to know for sure what is going on beyond conjecturing thattimeLeftis zero?What Nate said, but here is another explanation.
Imagine if you do this (where stopWatchTimer is a global or instance variable, doesn’t matter):
Now, do this:
The timer won’t invalidate, but it’ll still fire.
stopWatchTimeris a reference to the object. It isn’t the object itself. Thus, when you assign a second timer tostopWatchTimer, you are overwriting the reference to the first timer, but that timer is still going to fire!