块中的弱引用与 NSTimer 之间的区别
Difference between weak references in a block and a NSTimer
正如我们所知,我们需要在块内使用弱引用来打破保留循环,如下所示:
__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
有什么区别?计时器怎么还能保留目标呢?
基于选择器的 NSTimer
技术的全部问题是它建立了对传递给它的对象的强引用。因此,您用来保存对传递给 scheduledTimerWithTimeInterval
的目标的引用的变量本身是强还是弱并不重要。假设在基于选择器的调度计时器被调度时 target
引用不是 nil
,NSTimer
将建立自己的强引用。 "weak" 与 "strong" 调用代码中引用的性质仅指示 ARC 将在调用者代码中放置其自己的内存管理调用的位置,但 target
只是一个简单的指针,并且 none 的这种弱 vs 强信息被传达给 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
}];
正如我们所知,我们需要在块内使用弱引用来打破保留循环,如下所示:
__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
有什么区别?计时器怎么还能保留目标呢?
基于选择器的 NSTimer
技术的全部问题是它建立了对传递给它的对象的强引用。因此,您用来保存对传递给 scheduledTimerWithTimeInterval
的目标的引用的变量本身是强还是弱并不重要。假设在基于选择器的调度计时器被调度时 target
引用不是 nil
,NSTimer
将建立自己的强引用。 "weak" 与 "strong" 调用代码中引用的性质仅指示 ARC 将在调用者代码中放置其自己的内存管理调用的位置,但 target
只是一个简单的指针,并且 none 的这种弱 vs 强信息被传达给 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
}];