50

Possible Duplicate:
NSTimer doesn't stop

In my application I am using NStimer to call an animation function every 3 seconds. I want to stop this timer and called another event while the timer is still running. Is this possible?

Community
  • 1
  • 1

2 Answers2

106
@interface
    NSTimer *autoTimer;

@implementation

// Start timer
    autoTimer = [NSTimer scheduledTimerWithTimeInterval:(3.0)
        target:self 
        selector:@selector(autoTimerFired:) 
        userInfo:nil 
        repeats:YES];

// Stop timer:
    [autoTimer invalidate];
    autoTimer = nil;
zaph
  • 111,848
  • 21
  • 189
  • 228
44

First, you want to keep a pointer to the timer

self.packetTimer = [NSTimer timerWithTimeInterval:CONNECTION_TIMEOUT target:self selector:@selector(connectionTimeout:) userInfo:nil repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:packetTimer forMode:NSDefaultRunLoopMode];

If somewhere else in your code you want to cancel it, just call:

[self.packetTimer invalidate];
self.packetTimer = nil;
coneybeare
  • 33,113
  • 21
  • 131
  • 183
  • 1
    Shouldn't you release the timer before setting it to nil? `invalidate` will cause the run loop to release it's reference but there is an additional retain here when it's assigned to `packetTimer`. – Sebastien Martin Aug 29 '11 at 03:33
  • Hmm. This does not look corrected to me. Sebatsien is correct - when you assign the timer to self.packetTimer (assuming it is a retain property) then there is a retain. Adding it to the runloop is a second retain. When you invalidate it later, there is a release internally. I think you need an explicit [self.packetTimer release} just after the invalidate and just before setting self.packetTimer to nil. Am I wrong? – Marc Mar 28 '13 at 19:27
  • Yes, you are wrong. Setting it to nil releases it with a strong reference (retain property). – coneybeare Mar 28 '13 at 19:31
  • Aha! I never knew that when declaring a property to be retain or copy that setting the property to nil actually releases the property under the hood. It makes sense though: here is a good description: http://stackoverflow.com/questions/785260/what-happens-exactly-when-i-set-an-property-to-nil-in-the-dealloc-method . Thanks for the explanation. – Marc Mar 28 '13 at 19:36
  • Although, when adding to the run loop, the addTimer parameter should be self.packetTimer not just packetTimer. If you have just synthesized packetTimer so that "packetTimer" is the ivar then this is ok, but I always use _ivar rather than ivar as my ivar. In other words, @synthesize packetTimer = _packetTimer. Using addTimer:self.packetTimer would make this work. – Marc Mar 28 '13 at 19:48
  • Yes, there are many different irrelevant naming schemes here that could make or break this, the point of the answer, however, is to show how to invalidate a timer. – coneybeare Mar 28 '13 at 20:02