美文网首页
oc中block的循环引用 (一)

oc中block的循环引用 (一)

作者: 你买票吗 | 来源:发表于2019-11-20 15:17 被阅读0次

    @property (nonatomic, copy) void (^getCardInfo)(NSDictionary *cardInfo);
    @end
    两个点: copy和 block
    我将block声明为copy的原因是在代码块里面我可能会使用一些本地变量, 而block一开始是放在栈上的,只有copy后才会放到堆上。
    如果加copy属性,当其所在栈被释放的时候,这些本地变量将变得不可访问。一旦代码执行到block这段就会导致bad access。

    brush.getCardInfo = ^(NSDictionary *info){
    [self test];
    }
    但是这又带来另一个问题,就是self的引用计数+1。这意味着很可能会导致循环引用。self持有brush,brush持有block,block持有self。结果就是内存泄漏。

    解决办法如下. 通过一种方式, 告诉 block 这个变量的引用计数不要+1
    如果是 MRC的情况:

    __block CurrentViewController *blockself = self;
    brush.getCardInfo = ^(NSDictionary *info){
    [blockSelf test];
    }
    如果是 ARC的情况:

    __weak CurrentViewController *blockself = self;
    brush.getCardInfo = ^(NSDictionary *info){
    [blockSelf test];
    }
    1.解决办法
    简而言之就是一句话的事情

    weak typeof (self) weakself = self;
    经过上面的测试发现, 在加了
    weak 和__unsafe_unretained的变量引入后
    TestCycleRetain方法可以正常秩序 dealloc 方法 , 而不转换和用__block转换的变量都会引起循环引用
    因为防止循环引用的方法如下:

    _unsafe_unretained TestCycleRetain *weakSelf = self;
    网上大部分人的表述是"block 里面引用了 self 导致循环引用", 但是事实真的这样的吗? 我表示怀疑, 其实这种说话是不严谨的, 不一定是显式地出现"self"字眼才会引起循环引用, 我们改一下代码, 不通过属性 self.arr 去访问 arr 变量, 而是通过实例变量
    arr 去访问, 如下
    即使在你的代码没有显式地出现"self", 也会出现循环引用, 只要你在 block 里用到了 self 所拥有的东西, 但对于这种情况, 目前我不知道如何排除掉循环引用 , 因为我们无法通过加__weak 声明或者__block声明去禁止 block 对 self 进行强引用或者强制增加引用计数, 对于 self.arr 的情况, 我们要分两种环境去解决,

    MRC

    __block typeof(self) weakSelf = self,
    ARC

    weak typeof(self) weakSelf = self, 其实weak someClass *weakSelf = self也是 OK 的
    解决方式与上述基本一致, 只不过将
    block 关键字换成了
    weak, 这样的意思就是告诉 block, 咱们已经没有任何的关系, 不要在内部对 self 进行 retain 了

    相关文章

      网友评论

          本文标题:oc中block的循环引用 (一)

          本文链接:https://www.haomeiwen.com/subject/yemoictx.html