2

我有一个没有被释放的子类 UIView。我知道只有一个类正在创建我的视图的实例。我认为我有一个 NSTimer ivar。如果我注释掉该计时器并且当我点击此视图控制器上的取消按钮时,将调用此视图中的 dealloc。如果我不注释掉计时器,则永远不会调用 dealloc。

//CustomUIView
- (id) initWithFrame:(CGRect)frame 
{
    self = [super initWithFrame:frame];
    if (self) {
        _pollTimer = [[NSTimer scheduleTimerWithTimeInterval:0.2 target:self selector:@selector(onPollTimerFired:) userInfo:nil repeats:YES] retain];
    }
}

我想保留对这个计时器的引用,因为有时我希望暂停计时器。现在,我可以在我的视图上为计时器设置一个属性,并且在引用了我的自定义 uiview 的类的 dealloc 方法中,我可以在释放所述视图之前使其无效。我不太喜欢这种方法,因为我不想将此计时器暴露给外部实体。

有人有想法么?

4

3 回答 3

7

NSTimer始终保持其目标。这有两个含义:

  1. 您不应该让视图(这是计时器的目标)保留计时器,因为这会创建一个循环。

  2. 只要计时器保持活动状态,您的视图就永远不会被释放。

相反,您应该invalidate在视图完成时调用计时器。完成此操作后,视图将dealloc在其引用计数变为零时被吃掉。

通常,当视图从其父视图中移除时会发生这种情况;如果您希望它继续使用其计时器直到发生这种情况然后被释放,您可以覆盖removeFromSuperview以使计时器无效,然后调用super.

于 2012-06-24T05:25:02.113 回答
0

您不应该保留计时器。像这样安排计时器:_pollTimer = [NSTimer scheduleTimerWithTimeInterval:0.2 target:self selector:@selector(onPollTimerFired:) userInfo:nil repeats:YES];以及每当您想使其无效时:[_pollTimer invalidate]

于 2012-06-24T04:54:31.507 回答
0

编辑:

在你的-dealloc方法中,试试这个:

- (void) dealloc
{
    [_pollTimer invalidate];

    /*
        If not using ARC:
        [_pollTimer release], _pollTimer = nil;
        [super dealloc];
    */
}

你忘了调用super的执行-initWithFrame:!哎呀!

- (id) initWithFrame:(CGRect)frame 
{
    if ((self = [super initWithFrame:frame]))
    {
        _pollTimer = [[NSTimer scheduleTimerWithTimeInterval:0.2 target:self selector:@selector(onPollTimerFired:) userInfo:nil repeats:YES] retain];
    }
    
    return self;
}

这应该会更好。

于 2012-06-24T02:13:07.807 回答