【问题标题】:Difference between weak references in a block and a NSTimer块中的弱引用和 NSTimer 之间的区别
【发布时间】:2017-07-06 03:36:00
【问题描述】:

我们知道我们需要在块内使用弱引用来打破保留循环,如下所示:

__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

有什么区别?计时器如何仍然保留目标?

【问题讨论】:

  • 顺便说一句,我们在定义weakSelf时一般使用typeof(self)而不是id

标签: ios objective-c objective-c-blocks nstimer


【解决方案1】:

基于选择器的NSTimer 技术的全部问题在于它建立了对传递给它的对象的强引用。因此,用于保存对传递给scheduledTimerWithTimeInterval 的目标的引用的变量本身是强还是弱,都无关紧要。假设target 引用不是nil,在基于选择器的计划计时器被安排时,NSTimer 将建立自己的强引用。调用代码中引用的“弱”与“强”性质仅指示 ARC 将其自己的内存管理调用放置在调用者代码中的位置,但 target 只是一个简单的指针,这些弱与强信息都不是被传送到NSTimer。基于选择器的NSTimer 将建立自己的强引用,直到计时器为invalidated 时才会解析。

这就是为什么,当我们想要使通过基于选择器的方法构建的计时器无效时,我们必须在viewDidDisappear 或类似的地方设置它,而不是dealloc

注意,scheduledTimerWithTimeInterval 现在为 iOS 10 及更高版本提供了基于块的变体,因此如果您不必支持早期的 iO​​S 版本,您可以享受块的弱引用模式:

typeof(self) __weak weakSelf = self;
[NSTimer scheduledTimerWithTimeInterval:30 repeats:true block:^(NSTimer * _Nonnull timer) {
    // use weakSelf here
}];

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-06
    • 2012-09-02
    • 2013-07-06
    • 2012-10-03
    • 2018-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多