5

Can I send argument with @selector in NSTimer? If I want to release NSTimer, are the following steps right in dealloc?

[timer invalidate];
[timer release];
KlimczakM
  • 12,576
  • 11
  • 64
  • 83

4 Answers4

15

[timer release] only needs to be called if you "own" the timer. From Apple's documentation:

Because the run loop maintains the timer, from the perspective of memory management there's typically no need to keep a reference to a timer once you’ve scheduled it. Since the timer is passed as an argument when you specify its method as a selector, you can invalidate a repeating timer when appropriate within that method. In many situations, however, you also want the option of invalidating the timer—perhaps even before it starts. In this case, you do need to keep a reference to the timer, so that you can send it an invalidate message whenever is appropriate. If you create an unscheduled timer (see “Unscheduled Timers”), then you must maintain a strong reference to the timer (in a reference-counted environment, you retain it) so that it is not deallocated before you use it.

What does this mean?

If you alloc and init a timer, you must also release it, like so:

NSTimer * timer = [[NSTimer alloc] initWith...];

NSRunLoop * runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
[timer release];

...
...

[timer invalidate];
timer = nil;

Once the timer has been added to the run loop, there is no reason to keep a reference to it anymore, since the run loops owns it. In this case, as shown, you would release the timer as soon as you add it to the run loop, and then simply invalidate it when you are finished. The final line (setting timer to nil) is for safety. The call to invalidate will result in the timer being released (by the run loop), so it is unsafe to keep a reference that points to it. Setting the local reference to nil keeps things kosher.

If, however, you create a timer using one of the convenience methods like so:

NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval ...];

You do not need to call [timer release] at all! The convenience method adds the timer to the run loop, which then owns it, so you do not need to perform any memory management on the returned timer object. You would simply invalidate the timer when you no longer want to use it:

[timer invalidate];
timer = nil;

Or, if the timer was not set to repeat, you would do absolutely nothing at all, since it would be released after its first invocation.

e.James
  • 116,942
  • 41
  • 177
  • 214
  • 2
    as soon as you call [timer release], it isn't good form to assume that timer is still valid. In the case of a single method, you are almost always safe to do so, but the code would be better form if the [timer release] was placed after the [timer invalidate]. – Dennis Munsie Aug 01 '09 at 04:05
8

The two methods do different things. If you own a timer (you retained it, or alloced it, or copied it) then you should release it. If you scheduled it on a run loop, then you must invalidate it for the run loop to release it. If you did both things, then you must release and invalidate the timer (however usually having the run loop owning the timer is sufficient).

  • first release and then invalidate in deallocation? can i send argument with two arguments in selector? –  Jul 23 '09 at 12:12
  • First invalidate it, then release it (if you own it). Please clarify your last question. If you are asking whether you can call invalidate and release on the timer with only one call, the answer is no, unless you create your own convenience method that does these two things, and call that method. – Felixyz Jul 23 '09 at 12:30
  • can i send extra argument with @selector in NSTIMER? –  Jul 23 '09 at 12:44
1

Always, release is the last thing you do. Once you release something there is no guarantee it is safe to dereference the object, which means it no longer safe to send it ANY message.

Louis Gerbarg
  • 43,356
  • 8
  • 80
  • 90
0

That is the correct way to deallocate a timer that might still be running (and you want to stop).

Daniel Dickison
  • 21,832
  • 13
  • 69
  • 89
  • 1
    assuming that you own the timer in the first place... if you don't then the `-release` call will crash. Or should. –  Jul 23 '09 at 12:44