Can't invalidate, stop countdown NSTimer - Obj

2019-08-23 02:45发布

问题:

Problem is to stop NSTimer, for some reason [Timer invalidate] just not working...

Maybe my eyes are full of soap, but can't understand the reason why the timer didn't stop at 0, but go reverse counting -1, -2, -3 and so on...(((

I'm using epoch numbers as destination date. One more thing - my button "IBAction stop" with [Timer invalidate] works just fine - when i push it in simulator timer stops...

@implementation ViewController

- (void)viewDidLoad
{
[super viewDidLoad];


Timer = [NSTimer  scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateLabel) userInfo:nil repeats:YES];

}

- (IBAction) start {

Timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateLabel) userInfo:nil repeats:YES];


}
- (IBAction) stop {

[Timer invalidate];
Timer = nil;

}

-(void)updateLabel {

NSCalendar *calender = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
int units = NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents *components = [calender components:units fromDate:[NSDate date] toDate:destinationDate options:0];
[dateLabel setText:[NSString stringWithFormat:@"%d%c  %d%c  %d%c  %d%c", [components day], 'd', [components hour], 'h', [components minute], 'm', [components second], 's']];

destinationDate = [NSDate dateWithTimeIntervalSince1970:1355299710];

if (!destinationDate) {

    [Timer invalidate];
    Timer = nil;
}
}

回答1:

As Totumus pointed out, your if statement condition !destinationDate always evaluates to false, so your updateLabel method never invalidates your timer.

You have another bug too:

You're creating a timer in viewDidLoad and storing a reference to it in your Timer instance variable.

Then you're creating another timer in start and storing a reference to it in your Timer instance variable, overwriting the reference to the timer you created in viewDidLoad without invalidating that older timer.

So now you have two timers running, but you don't have a reference to the older timer, so you can never invalidate it.

Note that the run loop has a strong reference to a scheduled (running) timer, so even if you remove all of your strong references to it, the timer keeps running. That's why the invalidate message exists: to tell the run loop to remove its strong reference to the timer.