2011-10-02 86 views
0

每当我想打一个计时器,我只是做:NSTimer的内存管理 - 是否需要分配给变量?

[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]; 

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

回答

6

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

当计划计时器,运行循环保留它,并于所述定时器的参考它激发时沿着通过其选择 - 例如,(void) doTimerThing: (NSTimer *)tim - 被使用,所以它不是严格的你必须把它放入一个变量并保留它自己。 Apple在Timer Programming Topics文档的"Memory Management" section中解释得很清楚。

但是,如果您可能想在之前使计时器无效(或在重复计时器触发之间),那么您确实需要引用该计时器。在这种情况下,在它上面调用retain也是一个好主意。 scheduledTimerWithTimeInterval:target:...方法返回一个你不拥有的对象,并且你不应该对你不拥有的对象的内存状态做出假设(包括它们是否在autorelease池中,或者运行循环要运行多长时间保持计时器周围)。如果您需要定时器(或任何对象)继续存在,则应通过调用retain来声明所有权。


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

+0

你是什么意思应该总是有一个参数? – Snowman

+2

看看我收录的片段并阅读链接的文档。计时器的方法需要能够接受一个参数,一个“NSTimer”的实例。 –

3

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

由于命名约定建议,鉴于名字的方法scheduledTimerWithTimeInterval:...,你知道,它会返回一个自动释放的对象(或者更精确地说,它会返回一个对象,你是不是所有者,以及其你不需要自己发布发布)

如果不需要,你不必持有创建的NSTimer的引用:计时器将被安排在RunLoop上(这是RunLoop将会保留它直到它被使用,并在完成时释放它,这样你就不必担心了),所以它会自行生存。

但是如果您没有将返回的NSTimer存储在类似于第二个代码的变量中,那么您将无法取消定时器,如果您想要的话。尤其是,如果您设置了重复计时器,则需要将其存储在一个变量中,以便稍后可以访问该变量,特别是向其发送一条消息,以便取消该消息。

+0

'scheduledTimerWithTimeInterval:'does_not_ return a autoreleased object;它返回一个不属于调用者的对象。 –

+0

是的,但如果你阅读我的编辑,我解释了(以及在其他评论中)我的真正含义,并对我的意思做了精准的描述(如果你仔细阅读,我甚至在编辑之前已经解释过RunLoop保留计时器) – AliSoftware

+1

位于自动释放池中的对象仍然可以由其他对象拥有,并且不属于调用方的对象不必位于自动释放池中。他们不是一回事,也不应该混淆。 –

3

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

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

,而不是手动创建计时器。

+0

很酷,不知道! – Snowman

+0

这有没有什么好处呢? – Snowman

+0

@mohabitar:这会在幕后创建一个计时器,这是一种更简单,也许更易读的方法,可以在一段时间内延迟执行方法。 –