这让我困惑了一段时间。
我有一个NSTimer,添加到currentRunLoop,如果我不保留它,它会崩溃。
NSTimer *timer = [[NSTimer timerWithTimeInterval:60.0 target:self selector:@selector(tryUnion:) userInfo:nil repeats:NO] retain];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
我已经读过我不需要保留它,因为NSTunLoop的addTimer就是这样做的。
稍后我失效并释放(如果我不保留上述内容,我不会在下面发布 - 这是崩溃案例):
- (void) tryUnion:(NSTimer*)aTimer {
[aTimer invalidate];
[aTimer release];
}
我的问题是 1)如果没有保留/释放可以做我已经完成的事情,我应该如何写这个。 2)在“计时器”中分析标记此对象或潜在的对象泄漏。如此处所写,是否存在泄漏的可能性,或者只是分析器不够智能,不知道计时器调用的函数中是否有释放?
答案 0 :(得分:4)
规则是,如果你没有保留它,请不要释放它。 Here is a similar question which talks about that.因此,在您的示例代码中,我建议不要保留它,也不要发布它。
但那不是你的问题。您的问题是您已经创建了一个非重复计时器。您不需要使这些无效,它们在触发后会自动失效。来自NSTimer docs:
重复
如果是,则计时器将 反复重新安排自己,直到 无效。如果否,则计时器将是 火灾发生后失效。
所以你不应该保留/释放那个计时器,也不应该使它失效。火与忘记。
顺便说一句,如果您使用scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:
,那么也会为您完成向runloop添加计时器。所以你的整个事情就像:
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:60.0 target:self selector:@selector(tryUnion:) userInfo:nil repeats:NO];
您的计时器功能不需要对aTimer执行任何操作,只需执行计时器应该执行的任何操作;计时器将无效并在没有进一步干预的情况下释放。
答案 1 :(得分:1)
在计时器上调用invalidate会释放它,因此您不需要另外发布语句。请参阅文档here
答案 2 :(得分:1)
你是对的,NSTimer
不应该被保留。根据规则,类方法+(NSTimer *)timerWithInterval
应该是autorelease
的引用。
但是NSTimer的invalidate
消息将自己从NSRunLoop
中移除并释放它的引用(当时唯一剩下的引用)。您的第二次[aTimer release]
电话是导致崩溃的原因。