NSTimers导致泄漏 [英] NSTimers causing leaks

查看:104
本文介绍了NSTimers导致泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了很多关于NSTimers的内容,但我必须对它们做一些非常错误的事情,因为它实际上是泄漏工具中出现的所有泄漏。 责任框架栏目显示 - [NSCFTimer或+ [NSTimer(NSTimer)。

I've read up a lot about NSTimers, but I must be doing something very wrong with them, because it's practically all the leaks that show up in the Leaks Instrument. The "Responsible Frame" column says -[NSCFTimer or +[NSTimer(NSTimer).

所以这里是我在主菜单中设置NSTimer的方式。我把它简化为只显示定时器是如何设置的。

So here's how I have an NSTimer set up in my main menu. I shortened it up to just show how the timer is setup.

.h -

@interface MainMenu : UIView {
    NSTimer *timer_porthole;    
}

@end


@interface MainMenu ()

-(void) onTimer_porthole:(NSTimer*)timer;


@end

.m -

(在initWithFrame中)

(in initWithFrame)

- (id)initWithFrame:(CGRect)frame {

    self = [super initWithFrame:frame];
    if (self) {

        timer_porthole = [[NSTimer scheduledTimerWithTimeInterval:.05
                                                           target:self
                                                         selector:@selector(onTimer_porthole:)
                                                         userInfo:nil
                                                          repeats:YES] retain];

    }
    return self;
}   

离开视图时,它会杀死计时器:

When leaving the view, it kills the timers:

-(void) kill_timers{
     [timer_porthole invalidate];
     timer_porthole=nil;
}

当然,dealloc:

And of course, dealloc:

- (void)dealloc {
    [timer_porthole invalidate];
    [timer_porthole release];
    timer_porthole = nil;

    [super dealloc];
}


推荐答案

不要调用retain on你的NSTimer!

Don't call retain on your NSTimer!

我知道这听起来有点反直觉但是当你创建实例时它会自动注册到当前(probaby main)线程运行循环(NSRunLoop)。以下是Apple对此主题的评论...

I know it sounds counter-intuitive but when you create the instance it's automatically registered with the current (probaby main) threads run loop (NSRunLoop). Here's what Apple have to say on the subject...


计时器与run
循环一起使用。要有效地使用计时器,你需要知道运行循环
如何操作 - 参见NSRunLoop和Threading
编程指南。 请特别注意
运行循环保留其计时器,因此
你可以在将
添加到运行循环后释放计时器。

一旦在运行循环上安排,
计时器将以指定的间隔
触发,直到它失效。
非重复计时器在触发后立即使
无效。但是,重复计时器
,你必须通过调用invalidate方法
自己使计时器对象
无效。
调用此方法请求从当前
运行循环中删除
计时器;因此,你应该
总是从
中调用invalidate方法,该方法是安装了
的计时器的同一个线程。 使计时器
无效,立即禁用它,以便它不会影响运行循环
。运行
循环然后删除并释放
计时器,就在
invalidate方法返回之前或在某个
之后的点。一旦失效,计时器
对象就无法重复使用。

Once scheduled on a run loop, the timer fires at the specified interval until it is invalidated. A non-repeating timer invalidates itself immediately after it fires. However, for a repeating timer, you must invalidate the timer object yourself by calling its invalidate method. Calling this method requests the removal of the timer from the current run loop; as a result, you should always call the invalidate method from the same thread on which the timer was installed. Invalidating the timer immediately disables it so that it no longer affects the run loop. The run loop then removes and releases the timer, either just before the invalidate method returns or at some later point. Once invalidated, timer objects cannot be reused.




  • 引用来自Apple的NSTimer类引用。

    • Quotes are sourced from Apple's NSTimer class reference.
    • 所以你的实例化变成......

      So your instantiation becomes...

      timer_porthole = [NSTimer scheduledTimerWithTimeInterval:.05
                                                                 target:self
                                                             selector:@selector(onTimer_porthole:)
                                                               userInfo:nil
                                                                repeats:YES];
      

      现在您不再持有对该实例的引用,您不希望发布调用你的dealloc方法。

      And now that you're no longer holding the reference to the instance you wont want the release call in your dealloc method.

      这篇关于NSTimers导致泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆