正如我们所知,我们需要在块内使用弱引用来打破保留周期,如下所示:
__weak id weakSelf = self;
[self doSomethingWithABlock:^() {
[weakSelf doAnotherThing];
}]
然而,弱引用不能破坏由NSTimer
引起的保留周期。
__weak id weakSelf = self;
timer = [NSTimer scheduledTimerWithTimeInterval:30.0f
target:weakSelf
selector:@selector(tick)
userInfo:nil
repeats:YES]; // No luck
区别是什么?计时器如何仍然保留目标?
答案 0 :(得分:6)
基于选择器的NSTimer
技术的整个问题是它建立了对传递给它的对象的强引用。因此,用于保存对传递给scheduledTimerWithTimeInterval
的目标的引用的变量本身是强还是弱,是无关紧要的。假设target
引用在计划基于选择器的计划计时器时没有nil
,NSTimer
将建立自己的强引用。 "弱" vs" strong"调用代码中引用的性质仅指示ARC将在调用者代码中放置自己的内存管理调用的位置,但target
只是一个简单的指针,并且这些弱信息和强信息都不会被传达到NSTimer
。基于选择器的NSTimer
将建立自己的强引用,直到计时器为invalidated
才会解析。
这就是为什么当我们想要使通过基于选择器的方法构建的计时器无效时,我们必须在viewDidDisappear
之内,而不是dealloc
。
注意,scheduledTimerWithTimeInterval
现在有一个基于块的iOS 10及更高版本的变体,所以如果你不必支持早期的iOS版本,你可以享受块的弱参考模式:
typeof(self) __weak weakSelf = self;
[NSTimer scheduledTimerWithTimeInterval:30 repeats:true block:^(NSTimer * _Nonnull timer) {
// use weakSelf here
}];