什么情况下block会造成循环引用
ARC 情况下block
为了保证代码块内部对象不被提前释放,会对block
中的对象进行强引用,就相当于持有了其中的对象,而如果此时block
中的对象又持有了该block
,就会造成循环引用。
常见误区
- 所有block都会造成循环引用
- UIView的block动画不会造成循环引用。类方法不能强引用一个类,所以不会造成循环引用。
- Masonry约束block不会造成循环引用。view并没有持有该block。
- AFN、YTKNetwork等请求回调block不会造成循环引用。因为在block执行后,主动释放了block。
但是以上三种情况依然weakSelf
、strongSelf
结合使用不影响。
- block中只有self会造成循环引用
用下划线调用属性(如_name)也会出现循环引用,效果和使用self是一样的,因为内部会用self->name去查找。 - 通过
__weak __typeof(self) weakSelf = self;
可以解决所有block造成的循环引用
大部分情况下,这样使用是可以解决block循环引用,但是有些情况下这样使用会造成一些问题,比如在block中延迟执行一些代码,在还没有执行的时候,控制器被销毁了,这样控制器中的对象也会被释放,__weak对象就会变成null。所以会输出null。__strong __typeof(weakSelf)strongSelf = weakSelf;
可解。
如何避免
weakSelf
、strongSelf
结合使用。- 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;