每当我想制作计时器时,我就会这样做:
[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];
第一个是内存泄漏吗?使用它们的正确方法是什么?
答案 0 :(得分:7)
两个代码段都没有内存问题;您只需要选择与计时器交互的需求。
当你计划一个计时器时,运行循环会保留它,并且当它触发时它会传递对计时器的引用,它的选择器 - 例如(void) doTimerThing: (NSTimer *)tim
1 - 是使用,因此您不必将严格放入变量并自行保留。 Apple在计时器编程主题文档的"Memory Management" section中清楚地解释了这一点。
但是,如果您可能希望在之前使计时器无效(或者在重复计时器的触发之间),则需要对其进行引用。在这种情况下,最好在其上调用retain
。 scheduledTimerWithTimeInterval: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
消息,以便它可以被取消。