美文网首页
retain cycle循环引用

retain cycle循环引用

作者: 一个半吊子工程师 | 来源:发表于2020-09-22 22:55 被阅读0次

    block

    typedef void (^TestCircleBlock)();
    @property (nonatomic, copy) TestCircleBlock testObject;
    

    block在copy时都会对block内部用到的对象进行强引用的。

    self.testObject.testCircleBlock = ^{
       [self doSomething];
    };
    

    self将block作为自己的属性变量,而在block的方法体里面又引用了 self 本身,此时就很简单的形成了一个循环引用。

    应该将 self 改为弱引用

    __weak typeof(self) weakSelf = self;
     self.testObject.testCircleBlock = ^{
          __strong typeof (weakSelf) strongSelf = weakSelf;
          [strongSelf doSomething];
    };
    

    在 ARC 中,在被拷贝的 block 中无论是直接引用 self 还是通过引用 self 的成员变量间接引用 self,该 block 都会 retain self。

    我们发现上述这个方法确实解决所有问题,但是可能会有两个不理解的点:

    即使用weakSelf又使用strongSelf,这么做和直接用self有什么区别?
    为什么不会有循环引用?

    这是因为block外部的weakSelf是为了打破环循环引用,而block内部的strongSelf是为了防止weakSelf被提前释放,strongSelf仅仅是block中的局部变量,在block执行结束后被回收,不会再造成循环引用。

    这么做和使用weakSelf有什么区别?

    唯一的区别就是多了一个strongSelf,而这里的strongSelf会使self的引用计数+1,使得self只有在block执行完,局部的strongSelf被回收后,self才会dealloc。

    delegate

    在委托问题上出现循环引用问题已经是老生常谈了,规避该问题的杀手锏也是简单到哭:声明delegate时请用assign(MRC)或者weak(ARC),千万别手贱玩一下retain或者strong,毕竟这基本逃不掉循环引用了!

    delegate 属性的声明如下:

    @property (nonatomic, weak) id <TestDelegate> delegate;
    

    如果将 weak 改为 strong,则会造成循环引用

    // self -> ViewController
    ViewController *vc = [ViewController new];
    vc = self; 
    [self.navigationController pushViewController: vc animated:YES];
    
       // 假如是 strong 的情况
       // bVc.delegate ===> ViewController (也就是 A 的引用计数 + 1)
       // ViewController 本身又是引用了 <ViewControllerDelegate> ===> delegate 引用计数 + 1
       // 导致: ViewController <======> Delegate ,也就循环引用啦
    

    NSTimer:iOS开发-NSTimer探究

    相关文章

      网友评论

          本文标题:retain cycle循环引用

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