什么情况下block会造成循环引用

ARC 情况下block为了保证代码块内部对象不被提前释放,会对block中的对象进行强引用,就相当于持有了其中的对象,而如果此时block中的对象又持有了该block,就会造成循环引用。

常见误区

  • 所有block都会造成循环引用
  1. UIView的block动画不会造成循环引用。类方法不能强引用一个类,所以不会造成循环引用。
  2. Masonry约束block不会造成循环引用。view并没有持有该block。
  3. AFN、YTKNetwork等请求回调block不会造成循环引用。因为在block执行后,主动释放了block。
    但是以上三种情况依然 weakSelfstrongSelf结合使用不影响。
  • block中只有self会造成循环引用
    用下划线调用属性(如_name)也会出现循环引用,效果和使用self是一样的,因为内部会用self->name去查找。
  • 通过 __weak __typeof(self) weakSelf = self; 可以解决所有block造成的循环引用
    大部分情况下,这样使用是可以解决block循环引用,但是有些情况下这样使用会造成一些问题,比如在block中延迟执行一些代码,在还没有执行的时候,控制器被销毁了,这样控制器中的对象也会被释放,__weak对象就会变成null。所以会输出null。__strong __typeof(weakSelf)strongSelf = weakSelf;可解。

如何避免

  • weakSelfstrongSelf结合使用。
  • block的外部对象使用weak,比如用weak修饰property。
  • 将持有block的对象置空,或者block执行后将block置空。如:
self.one = [[TestObject alloc] init];
self.two = [[TestObject alloc] init]; 
self.one.blockProperty = ^{
    NSLog(@"%@", _two);
};
self.one.blockProperty();
self.one.blockProperty = nil;
或者 self.one = nil;