ibireme / YYKit

A collection of iOS components.
MIT License
13.99k stars 3.69k forks source link

关于在block引用self时,先weak再strong的疑问。 #226

Open Mryong opened 8 years ago

Mryong commented 8 years ago

下面的代码是从YYCache中拷贝的,

- (void)_trimRecursively {
    __weak typeof(self) _self = self;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_autoTrimInterval * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
        __strong typeof(_self) self = _self;
        if (!self) return;
        [self _trimInBackground];
        [self _trimRecursively];
    });
}

我有些疑问,首先我觉得 __weak typeof(self) _self = self; __strong typeof(_self) self = _self; 这两句没必要写,先weak再strong 和原来的self有什么区别呢? 原来的self指针就是strong类型啊。

其次我觉得 if (!self) return 这个条件永远不会成立,因为这时候已经定了strongSelf强指针指向self对象,所以self的对象的引用计数必然已经+1了,直到block释放的时候才会-1,而此时显然blokc还没释放,所以self指向的对象的应用计数必然大于等于1,所以不会释放,所以!self条件必然不会成立。

z234009184 commented 8 years ago

很有必要的哦,如果【block内部】使用【外部声明的强引用】访问【对象A】, 那么【block内部】会自动产生一个【强引用】指向【对象A】 如果【block内部】使用【外部声明的弱引用】访问【对象A】, 那么【block内部】会自动产生一个【弱引用】指向【对象A】,正是因为如此才加的判断啊。因为block中使用了外部声明的弱引用,所以里面的self也是弱的,容易没命的 我跟你讲。

ibireme commented 8 years ago

如果直接引用 strong self,那 block 创建时就会立刻强引用了 self;而如果先用 weak 引用,则 block 创建时对 self 是弱引用,而直到 block 开始执行时,self 才会被强引用。

如果 block 提交到 queue 但还未执行的时候,整个 Cache 对象被释放了,那这时 weak self 就会变为 nil 了,而后 block 执行的时候 if (!self) return; 就会成立了。

Tbwas commented 8 years ago

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_autoTrimInterval * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 这里直接引用self应该不会发生循环引用啊 });