9
@interface someview:UIView{
  NSTimer* timer;
}
@end

@implementation someview

-(void)dealloc{
  NSLog(@"dealloc someview");
  [timer invalidate];
  timer = nil;
}
-(void)runTimer{
//
}
-(void)someMethod{

  timer = [NSTimer timerWithTimeInterval:2.0f target:self selector:@selector(runTimer) userInfo:nil repeats:YES];
}

@end

释放 someview 不会调用 dealloc 并且计时器会继续运行。

如果我注释掉“timer = [NSTimer schedule....”部分,将调用 dealloc。这意味着我的代码的所有其他部分都可以正常工作,而计时器是罪魁祸首。runTimer 方法是空的,这意味着它只是在搞乱我的计时器。

4

3 回答 3

23

我认为在 UIView 内使用 NSTimer 时最好的解决方案是覆盖 removeFromSuperview 方法;

- (void)removeFromSuperview
{
    [timer invalidate];
    timer = nil;

    [super removeFromSuperview];
}

这里唯一要记住的是,您需要确保计时器不是 nil 对象,因为 removeFromSuperview 也可以从其他 UIView 的超级 dealloc 方法中自动调用。你可以换一个条件来检查。

于 2011-05-19T18:54:23.980 回答
14

NSTimer 保留目标。因此,在您的视图被释放之前,计时器必须无效。

于 2011-04-14T22:30:53.057 回答
1

如上所述,计时器保留了它们的目标。直到定时器失效,定时器和视图之间存在一个retain循环,所以视图不会被释放。

当通过子类化从视图层次结构中删除计时器时,我会使计时器无效,didMoveToSuperview当存在与视图相关的更改(例如,超级视图更改)时,系统会调用它。'removeFromSuperview' 仅removeFromSuperview在 UIView 上调用时调用

- (void)didMoveToSuperview
{
    [super didMoveToSuperview];

    if (!self.superview)
    {
        [timer invalidate];
        timer = nil;
    }
}
于 2013-12-18T15:28:45.240 回答