NSTimer的内存管理 - 是否需要将其分配给变量?

时间:2011-10-02 17:40:48

标签: objective-c cocoa memory-leaks nstimer foundation

每当我想制作计时器时,我就会这样做:

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

而不是

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

第一个是内存泄漏吗?使用它们的正确方法是什么?

3 个答案:

答案 0 :(得分:7)

两个代码段都没有内存问题;您只需要选择与计时器交互的需求。

当你计划一个计时器时,运行循环会保留它,并且当它触发时它会传递对计时器的引用,它的选择器 - 例如(void) doTimerThing: (NSTimer *)tim 1 - 是使用,因此您不必将严格放入变量并自行保留。 Apple在计时器编程主题文档的"Memory Management" section中清楚地解释了这一点。

但是,如果您可能希望在之前使计时器无效(或者在重复计时器的触发之间),则需要对其进行引用。在这种情况下,最好在其上调用retainscheduledTimerWithTimeInterval:target:...方法返回一个您不拥有的对象,您不应该假设您不拥有的对象的内存状态(包括它们是否在自动释放池中,或者运行多长时间)循环将保持计时器周围)。如果您需要使用计时器(或任何对象),您应该通过调用retain对其进行所有权声明。


1 请注意,计时器的方法应始终为have one parameter;您的代码段中的选择器看起来像是一个没有的方法。计时器似乎以这种方式工作,但是你的操作与文档化的界面相反。

答案 1 :(得分:4)

除了之前的答案,如果您不需要重复计时器,可以使用

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

而不是手动创建计时器。

答案 2 :(得分:3)

无论哪种方式,都没有内存泄漏。第二个解决方案只是将结果影响到变量,而第一个解决方案不存储结果,但效果是相同的。

正如命名约定所示,给定方法的名称scheduledTimerWithTimeInterval:...,您知道它将返回一个自动释放的对象(或者更准确地说,它将返回一个您不是所有者,您不必自己发送版本)

如果不需要,您不必保留对创建的NSTimer的引用:计时器将在RunLoop上进行调度(这是RunLoop将保留它直到使用它,并在以后释放它完成了,所以你不必费心,所以它会自己生活。

但是如果你没有将返回的NSTimer存储在第二个代码中的变量中,那么如果你愿意,你将无法取消定时器。特别是,如果你设置了一个重复计时器,你需要将它存储在一个变量中,以便以后可以访问它,特别是发送一条invalidate消息,以便它可以被取消。