美文网首页
Block循环引用实例讲解

Block循环引用实例讲解

作者: 9fda4b908fad | 来源:发表于2017-02-27 15:42 被阅读87次

    接上篇block实现原理探究,本篇为上篇的补充篇,如果有兴趣,可以看看上篇的内容(链接在这里),两篇内容的偏向有所不同,所以不用担心,会影响到本篇阅读.

    block循环引用在日常开发过程中,是肯定会遇到的问题,除非你不使用block.但是可能有部分的小伙伴对这个问题没有深入的研究过,在这里,我希望抛砖引玉,希望能帮助到你.如果文中有不对的地方,欢迎指正.

    下面开始进入正题:

    下面以三种情形的方式分析,以下代码全部循环引用的全部代码

    @interface TestViewController ()
    
    @property (nonatomic,copy) void (^testBlock)();
    
    @property (nonatomic,strong) Person *person;
    
    
    @end
    
    @implementation TestViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
       
        self.view.backgroundColor = [UIColor purpleColor];
        
        //情况一
       [self situationOne];
        
        //情况二
    //    [self situationTwo];
        
        //情况二
    //    [self situationThree];
    }
    
    - (void)situationOne
    {
      
        self.testBlock = ^{
            
            NSLog(@"%@",self);
        };
        
        
    }
    
    - (void)situationTwo
    {
        Person *p = [[Person alloc] init];
    
        p.block = ^{
            
            NSLog(@"%@",p);
        };
      
    }
    
    - (void)situationThree
    {
        Person *p = [[Person alloc] init];
        
        p.block = ^{
            
            NSLog(@"%@",self);
        };
        
        self.person = p;
    
    }
    
    
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
    {
        [self dismissViewControllerAnimated:true completion:nil];
    }
    
    
    -(void)dealloc
    {
        NSLog(@"%s:The CurrentViewController is Dealloc",__func__);
    }
    
    @end
    
    

    另外一个Person文件

    @interface Person : NSObject
    
    @property (nonatomic,copy) void (^block)();
    
    @end
    
    • 情形一:
      这种情况我们可以看到VC(这里就是self)当中有个testBlock,而testBlock中又引用了VC,这两者之间就形成一个引用环,导致VC没有办法释放.

    • 情形二:
      这种情况和情形一类似,Person和block之间产生了一个引用环,导致Person没有办法释放
      这里需要解释一点的是,有些小伙伴认为这里没有循环引用,因为他们觉得没有对象对person强引用,出了这个方法自然就被销毁了,其实这个理解是有误的,block对person的引用不应该被忽略

    解决上面两种情况循环引用的办法一样,就是让block里面引用外部的变量的形式变成弱引用,使引用环没有办法形成,以情形一为例,代码应该改为:

       __weak typeof(self) _self = self;
        
        self.testBlock = ^{
            
            NSLog(@"%@",_self);
        };
    
    • 情形三:
      这种情况牵扯到几个对象,而且编译器不会提示你有循环引用存在的问题存在,所以相对上面情况比较隐蔽一点,其实认真分析以下也不难发现 : person引用block,block引用VC(这里指的是self),VC当中又引用了person,一个引用环就产生了,解决的办法也很简单,只要block中的那一环断掉就行了,即:
        Person *p = [[Person alloc] init];
        
        __weak typeof(self) _self = self;
        
        p.block = ^{
            
            NSLog(@"%@",_self);
        };
        
        self.person = p;
    

    注: 以上代码在ARC环境下适用,如果在MRC的环境下,你需要将 __weak换成 __block

    以上基本上就是开发中遇到比较多的循环引用的情况了,当然还要更加隐蔽的循环引用的情况存在,但是只要我们仔细一层一层的分析,还是能够发现的,多谢阅读.

    相关文章

      网友评论

          本文标题:Block循环引用实例讲解

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