开发者

NSTimer, to retain or not to retain

开发者 https://www.devze.com 2023-03-07 02:08 出处:网络
This is something that has puzzled me for awhile. I have a NSTimer, added to the currentRunLoop, and if I don\'t retain it, it crashes.

This is something that has puzzled me for awhile.

I have a NSTimer, added to the currentRunLoop, and if I don't retain it, it crashes.

NSTimer *timer = [[NSTimer timerWithTimeInterval:60.0 target:self selector:@selector(tryUnion:) userInfo:nil repeats:NO] retain];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

I have read that I don't need to retain it, as addTimer to th开发者_运维技巧e NSRunLoop does that.

later I invalidate and release (if I don't retain above, I don't release below- that's the crashing case):

- (void) tryUnion:(NSTimer*)aTimer {
[aTimer invalidate];
[aTimer release];
}

My questions are 1) How should I write this, if its possible to do what i've done without the retain/release. 2) analyze flags this or a potential leak of the object in "timer". As written here, is there the possibility of leaks, or is it just that analyzer isn't smart enough to know that there is a release in the function called by the timer?


The rule is, don't release it if you didn't retain it. Here is a similar question which talks about that. So in your example code I would suggest not retaining it, and not releasing it.

But that's not your issue. Your issue is that you've created a non-repeating timer. You don't need to invalidate those, they invalidate themselves after they fire. From the NSTimer docs:

repeats
If YES, the timer will repeatedly reschedule itself until invalidated. If NO, the timer will be invalidated after it fires.

So you should neither retain/release that timer, nor invalidate it. Fire and forget.

As an aside, if you use scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:, the adding of the timer to the runloop is done for you as well. So your whole thing would be like:

NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:60.0 target:self selector:@selector(tryUnion:) userInfo:nil repeats:NO];

Your timer function doesn't need to do anything with aTimer, just do whatever thing your timer is supposed to do; the timer will be invalidated and released without further intervention.


Calling invalidate on a timer releases it so you don't need to have another release statement. See the docs here


Well you're right in that the NSTimer shouldn't have to be retained. The class method +(NSTimer *)timerWithInterval should, by rule, autorelease it's reference.

But NSTimer's invalidate message removes itself from the NSRunLoop and that releases it's reference (the only one left at the time). Your second [aTimer release] call is the cause of the crash.

0

精彩评论

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

关注公众号