iOS block 简单循环引用,大环引用(为什么用 __wea
2019-12-16 本文已影响0人
孙掌门
ios block 简单循环引用,大环引用(为什么用 __weak 修饰可以打破循环引用,怎样做断环操作)
分析下面的代码
_arr = [NSMutableArray arrayWithObject:@"sunchengxiu"];
_blk = ^ NSString *(void){
return [NSString stringWithFormat:@"i am %@",_arr[0]];
};
_blk();
上面的代码会发生循环引用,因为当前对象对 blk 进行了强引用,而_blk又对当前对象arr进行了强引用,所以就引起了循环引用
解决方法
_arr = [NSMutableArray arrayWithObject:@"sunchengxiu"];
__weak NSArray *weakAArr = _arr;
_blk = ^ NSString *(void){
return [NSString stringWithFormat:@"i am %@",weakAArr[0]];
};
_blk();
第一种解决方案是将当前arr 弱引用
为什么用 __weak 就可以解决
在之前的文章中,讲过截获变量,当block截获对象变量的时候,会连同他的修饰符一起截获,这里weakAArr是个对象,当block截获他的时候,会连同他的修饰符__weak一起截获到block的结构体中,所以,这样block就不会对self的arr产生强引用,这就解释了为什么用__weak修饰就可以打破循环引用。
进阶(大环引用)
self.name = @"sunchengxiu";
__block ViewController *vc = self;
_blk = ^ NSString *(void){
return [NSString stringWithFormat:@"i am %@",vc.name];
};
_blk();
在arc下会产生循环引用:
当前对象引用了_blk,_blk又强引用了__block变量,而__block又是对原有对象的引用,所以就形成了
当前对象 -> Block -> __Block 变量 -> 当前对象,这样一个大环引用.
断环操作
self.name = @"sunchengxiu";
__block ViewController *vc = self;
_blk = ^ NSString *(void){
NSString *name = [NSString stringWithFormat:@"i am %@",vc.name];
vc = nil;
return name;
};
NSString *name = _blk();
NSLog(@"%@",name);
我们在其中加上这样一句,vc = nil;
就可以断环,但会有一个问题,如果不调用block,那么就一直会有引用,就不会释放。