我正在使用这样的 NSTimer
:
timer = [NSTimer scheduledTimerWithTimeInterval:30.0f target:self selector:@selector(tick) userInfo:nil repeats:YES];
当然,NSTimer
会保留创建保留循环的目标。此外, self
不是 UIViewController 所以我没有像 viewDidUnload
这样的东西,我可以使计时器无效以打破循环。所以我想知道是否可以改用弱引用:
__weak id weakSelf = self;
timer = [NSTimer scheduledTimerWithTimeInterval:30.0f target:weakSelf selector:@selector(tick) userInfo:nil repeats:YES];
我听说计时器必须无效(我猜是从运行循环中释放它)。但是我们可以在我们的 dealloc 中做到这一点,对吧?
- (void) dealloc {
[timer invalidate];
}
这是一个可行的选择吗?我见过很多人处理这个问题的方法,但我没有看到这个。
最佳答案
建议的代码:
__weak id weakSelf = self;
timer = [NSTimer scheduledTimerWithTimeInterval:30.0f target:weakSelf selector:@selector(tick) userInfo:nil repeats:YES];
具有以下效果: (i) 对自身进行了弱引用; (ii) 读取弱引用是为了提供指向 NSTimer
的指针。它不会产生创建具有弱引用的 NSTimer
的效果。该代码和使用 __strong
引用之间的唯一区别是,如果在给定的两行之间释放了 self ,那么您会将 nil
传递给计时器。
您能做的最好的事情就是创建一个代理对象。比如:
[...]
@implementation BTWeakTimerTarget
{
__weak target;
SEL selector;
}
[...]
- (void)timerDidFire:(NSTimer *)timer
{
if(target)
{
[target performSelector:selector withObject:timer];
}
else
{
[timer invalidate];
}
}
@end
然后你会做这样的事情:
BTWeakTimerTarget *target = [[BTWeakTimerTarget alloc] initWithTarget:self selector:@selector(tick)];
timer = [NSTimer scheduledTimerWithTimeInterval:30.0 target:target selector:@selector(timerDidFire:) ...];
或者甚至向 BTWeakTimerTarget 添加一个 +scheduledTimerWithTimeInterval:target:selector:...
形式的类方法,以创建更简洁的代码形式。您可能希望公开真正的 NSTimer
以便您可以 invalidate
它,否则建立的规则将是:
https://stackoverflow.com/questions/16821736/