LD面试题之(真懂)系列

Block的循环引用探究

2018-07-18  本文已影响16人  LD_左岸
Block属性修饰用copy 在将block由栈区 拷贝到堆区后block内部会自动产生对外界的强或弱引用
如果[Block内部]使用[外界声明的强引用]访问[对象A],那么[Block内部]会产生一个[强引用]指向[对象A]
如果[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]

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

猜你喜欢

热点阅读