Neal Caffrey
Neal Caffrey

Reputation: 133

How to cancel previous NSTimer if new is fired

I try to show/hide view by tap using nstimer.

    @interface
        @property (nonatomic, retain)NSTimer *timer;
        UIView *view;
        @implementation
        view.hiden=YES;
        - (void)handleTap:(UITapGestureRecognizer *)sender{
        if([timer isValid)]{
timer.invalidate;///that gives me _EXC_BAD_ACCESS
}
        view.hiden=NO;
        timer = [NSTimer scheduledTimerWithTimeInterval:3.0
                                                     target:self
                                                   selector:@selector(targetMethod)
                                                   userInfo:nil
                                                    repeats:NO];


        }
        -(void)targetMethod{
        view.hiden=YES;
        }

If you understand something of this code, you can see the problem. If I tap once and wait 3 seconds, everthing is fine.But if I tap on it and tap again after 1.5 seconds, it should make another timer case and hide it after 3 seconds, but it hide it after 1.5 seconds, because old one is firing.

As you can see, I tried to invaliditate it but gives me error.

So how can I destroy it in proper way?

Upvotes: 1

Views: 417

Answers (4)

Steven Fisher
Steven Fisher

Reputation: 44876

Like this:

- (void)timerFired:(id)sender {
    _timer = nil;
    // do thing here
}

- (IBAction)handleTap:(id)sender {
    [_timer invalidate];
    _timer = [NSTimer scheduledTimerWithTimeInterval:3.0
                                              target:self
                                            selector:@selector(timerFired:)
                                            userInfo:nil
                                             repeats:NO];
}

- (void)dealloc {
    [_timer invalidate];
}

There's a few key things you need to do here:

  • In the code that handles the firing of the timer, set the instance variable to nil.
  • Invalidate the old timer before creating the new one.
  • Don't worry about checking the timer's validity before invalidating it. If you follow this technique, the timer will either be valid or nil. It's perfectly safe to call invalidate on nil.
  • You don't have to nil _timer between invalidating it and reassigning it; this code is all on the main thread. If you were just cancelling the timer, though, you would.
    • The reason for this is that this timer has been scheduled on the runloop. That guarantees it won't fire until the next iteration of the runloop. The runloop will not iterate until you return.
  • In dealloc, you should invalidate the timer. (It might be more appropriate for you to do this in viewDidDisppear:; if you do, make sure you nil it after.)

Upvotes: 2

Gavin
Gavin

Reputation: 8200

After you invalidate the timer, set the property to nil so that the next time you come thru it, you're not pointlessly holding onto an invalidated timer.

Upvotes: 0

Sam B
Sam B

Reputation: 27608

//before firing a timer null it always
[timer invalidate];
timer=nil;

//now create a new instance of it
timer = [NSTimer scheduledTimerWithTimeInterval:3.0
                                                     target:self
                                                   selector:@selector(targetMethod)
                                                   userInfo:nil
                                                    repeats:NO];

Upvotes: 0

Avt
Avt

Reputation: 17043

Use

[timer invalidate];

NSTimer

Upvotes: 0

Related Questions