开发者

Memory management of NSTimer -- does it need to be assigned to a variable?

Whenever I want to make a timer, I just do:

[NSTimer scheduledTimerWithTimeInterval:5.0 
                                 target:self 
                               selector:@selector(someMethod) 
                               userInfo:nil 
                                repeats:NO];

rather than

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:5.0 
                                                  target:self 
                                                selector:@selector(someMethod) 
                                              开发者_如何学Go  userInfo:nil 
                                                 repeats:NO];

Is the first one a memory leak? What's the correct way to use them?


You have no memory problem in either snippet; you simply have to make a choice about your needs for interacting with the timer.

When you schedule a timer, the run loop retains it, and a reference to the timer is passed along when it fires and its selector -- e.g., (void) doTimerThing: (NSTimer *)tim1 -- is used, so it isn't strictly necessary for you to put it into a variable and retain it yourself. Apple explains this pretty clearly in the "Memory Management" section of the Timer Programming Topics doc.

If, however, you might want to invalidate the timer before it fires (or in between fires for a repeating timer), you do need to have a reference to it. In that case, it is also a good idea to call retain on it. The scheduledTimerWithTimeInterval:target:... method returns an object that you do not own, and you should not make assumptions about the memory status of objects you don't own (including whether they are in an autorelease pool or not, or how long the run loop is going to keep the timer around). If you need the timer (or any object) to stick around, you should make a claim of ownership on it by calling retain.


1 Note that a timer's method should always have one parameter; the selector in your snippet looks like it is for a method that does not. The timer seems to work that way, but you're operating contrary to the documented interface.


In addition to previous answers, if you don't need repeating timer, you can use

[self performSelector:@selector(someMethod) withObject:nil afterDelay:5.0];

instead of creating timer manually.


In either way, there is no memory leak. The second solution is just affecting the result to a variable, whereas the first one don't store the result, but the effect are the same.

As the naming convention suggests, given the name scheduledTimerWithTimeInterval:... of the method, you know that it will returns an autoreleased object (or to be more precise, it will return an object which you are not the owner, and for which you won't have to send a release to by yourself)

You don't have to hold a reference to the created NSTimer if not needed: the timer will be scheduled on the RunLoop (and that's the RunLoop that will retain it until it is used, and release it when done, so you don't have to bother), so it will live by itself.

But if you don't store the returned NSTimer in a variable like in your second code, you won't be able to cancel the timer if you ever wanted to. Especially, if you setup a repeating timer, you will need to store it in a variable so that you can access it later, especially to send it an invalidate message so it can be cancelled.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜