Block的循环引用探究

作者: LD_左岸 | 来源:发表于2018-07-18 15:32 被阅读16次
    Block属性修饰用copy 在将block由栈区 拷贝到堆区后block内部会自动产生对外界的强或弱引用
    • 具体是对外界产生强引用 还是弱引用 可根据以下原则判断:
    如果[Block内部]使用[外界声明的强引用]访问[对象A],那么[Block内部]会产生一个[强引用]指向[对象A]
    • 如下图 block内部 使用外界声明的强引用p访问对象p的name属性 那么block内部会产生一个强引用指向对象p
    • 这样导致对象p对block强引用(copy)
      block内部又对 对象p产生了强引用


      Snip20180718_1.png
    如果[Block内部]使用[外界声明的弱引用]访问[对象A],那么[Block内部]会产生一个[弱引用]指向[对象A]
    Person * p = [[Person alloc]init];
        p.name = @"Bulice";
        __weak Person * weakP = p;
        p.block = ^{
            NSLog(@"%@",weakP.name);
        };
    

    block外部使用__weak
    block内部使用__strong

     Person * p = [[Person alloc]init];
        p.name = @"Bulice";
        __weak Person * weakP = p;
        p.block = ^{
            NSLog(@"block1---%@",weakP.name);
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                NSLog(@"block2---%@",weakP.name);
            });
        };
        p.block();
    
    [4356:345984] block1---Bulice
    [4356:345984] -[Person dealloc]
    [4356:345984] block2---(null)
    
    • 对打印结果分析如下

    由于Block1 和 Block2内部 都使用了外部的弱引用 所以Block1执行完之后 除了GCD的Block(GCD内部对延时Block有强引用)之外 剩下的对象都销毁了(局部变量)
    这样就导致了延时Block里相当于 nil.name


    RAC和YYKit中都有 Block外部使用弱引用 内部使用强引用的宏
    他们为什么这么做
    代码分析如下

    - (void)viewDidLoad {
        [super viewDidLoad];
        Person * p = [[Person alloc]init];
        p.name = @"Bulice";
        __weak Person * weakP = p;
        p.block = ^{
            __strong Person * strongP = weakP;
            NSLog(@"block1---%@",strongP.name);
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                NSLog(@"block2---%@",strongP.name);
            });
        };
        p.block();
        
    }
    
     block1---Bulice
     block2---Bulice
     [Person dealloc]
    
    • block1引用外部的weakP是安全的
    • 在内部创建一个强指针去指向 person 对象,因为在内部声明变量,Block 是不会强引用这个对象的,这也就在避免了循环引用风险的同时,又创建出了一个强指针指向对象。
    • 之后再 Block2 来引用相对于它来说是外部的变量 strongP ,
    • 这时 Block2 会默认创建出来一个强引用来引用 p 对象,
    • 当block1的作用域结束之后 strongP 会跟着被销毁,内存中就仅剩下了Block2 强引用着 p 对象 所以p的属性值在block2执行时 可以访问到。

    鉴于能力一般 水平有限 理解有误之处 深望不吝指出 阿门

    相关文章

      网友评论

        本文标题:Block的循环引用探究

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