Reputation: 6362
I have declared an NSTimer
in my UIViewController
header as such:
NSTimer *mainTimer;
And I start it up in the viewWillAppear
method in the implementation, so:
mainTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateAll) userInfo:nil repeats:YES];
I have a button that flips the view over (standard utility app template) called showInfo
and it has the command:
[mainTimer invalidate];
When my app launches, the timer starts and does it's thing. The first time I tap that button and the view flips, the timer stops. When I'm done with the flipSideViewController
and the main view reappears, the timer starts again. So far, good. The problem is that subsequent button presses (and thus calls to [mainTimer invalidate]
don't make the timer stop. It just keeps going. I can flip back and forth all I want and it continues to update. For grins, I put two invalidate
calls in a row, but that crashes.
UPDATE:
Found the problem. Upon returning from the flipSideViewController
, I was calling viewWillAppear
myself, which would create the timer. The run loop also calls viewWillAppear
automatically, so a second timer was created. This only happened after I had visited the flip side once so the timer (single instance) would stop normally when I flipped the first time. Odd that I can create two timers with the same name though...
Upvotes: 0
Views: 994
Reputation: 15889
It is possible viewWillAppear is called several times.
You should make sure the timer is invalidated before creating it
[mainTimer invalidate];
mainTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateAll) userInfo:nil repeats:YES];
Of course, if you are also invalidating the timer on some other place, you should assign it to null.
[mainTimer invalidate];
mainTimer = NULL;
Upvotes: 1
Reputation: 162722
Once a timer is invalidated, it will never fire again.
Thus, if the "timer keeps going", then it is a different timer. Make sure that you are speaking to the instances you think you are. I've seen quite a few bugs where developer alloc/init an instance and then load a NIB and cause a different instance of a particular class to come into play. I could see something similar happening here.
Note that it is impossible to invalidate a timer in the dealloc of the object that is the target of the timer. The timer will retain the target and, thus, the target cannot be [correctly] deallocated within the timer first being invalidated.
Upvotes: 3
Reputation: 5245
From the docs for [NSTimer invalidate]
:
Stops the receiver from ever firing again and requests its removal from its run loop.
So I would call invalidate and then release your timer. It doesn't look like you're retaining on the timer in the first place. So, retain the timer when you make it, invalidate it when you want to, then release after the invalidate.
Next viewWillAppear, make sure you're making and retaining on a new timer.
Upvotes: 1
Reputation: 10733
I just did exactly the same, and it seems to work for me. What I did in the xcode template:
Go to MainViewController.h and type:
@interface MainViewController : UIViewController <FlipsideViewControllerDelegate> {
NSTimer* timer;
}
@property (nonatomic, retain) NSTimer* timer;
- (IBAction)showInfo:(id)sender;
@end
Go to MainViewController.m and add:
@synthesize timer;
-(void) viewWillAppear:(BOOL)animated {
NSLog(@"Timer!");
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateAll) userInfo:nil repeats:YES];
}
-(void) updateAll {
NSLog(@"run");
}
- (IBAction)showInfo:(id)sender {
[timer invalidate];
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:@"FlipsideView" bundle:nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
[controller release];
}
Just that, and it runs well for me. Does this help somehow? Maybe your problem is somewhere else - what do you do in updateAll
?
Upvotes: 2