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,那么就一直会有引用,就不会释放。

上一篇 下一篇

猜你喜欢

热点阅读