ARC下NSStackBlock去哪了

我在 Objective-C中Block的类型 一文中说到MRC下有NSGlobalBlock、NSMallocBlock以及NSStackBlock三种类型的block,而ARC下是没有NSStackBlock类型的,在这里对其进行一个更正补充。


在RAC下,进行如下测试:

    CGFloat f = 1.1;
    
    NSLog(@"%@", ^{NSLog(@"%lf",f);});
    
    NSLog(@"%@",[^{NSLog(@"%lf",f);} copy]);
    
    void(^deliveryBlock)(void) = ^{NSLog(@"%lf",f);};
    NSLog(@"%@", deliveryBlock);

输出日志为

2017-03-24 22:20:22.526 testdemo[48961:588668] <__NSStackBlock__: 0x7fff525a8c20>
2017-03-24 22:20:22.526 testdemo[48961:588668] <__NSMallocBlock__: 0x60000005e420>
2017-03-24 22:20:22.527 testdemo[48961:588668] <__NSMallocBlock__: 0x60000005e420>

我发现,在直接打印block的时候,他的类型显示的还是NSStackBlock。而我们将这个block进行赋值之后,打印deliveryBlock的结果是NSMallocBlock类型。
也就是说,NSStackBlock类型在ARC下是存在,只是在对他进行赋值的时候,编译器将栈区的block拷贝到了堆区(赋值和copy在这里效果相同)。


至于原因

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSObject *obj = [[NSObject alloc]init];
    void(^deliveryBlock)(void) = ^{
        NSLog(@"%@",obj);
    };
    [self didBlock:deliveryBlock];
}


- (void)didBlock:(void(^)(void)) block {
    NSLog(@"%@",block);
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        block();
    });
}

参照上方代码,假如deliveryBlock是NSStackBlock类型,如果我们把deliveryBlock当作方法参数传递到了另外一个方法,那么一旦deliveryBlock不在原来方法的调用栈,而新方法调用deliveryBlock的时机又不得而知,可能在新方法调用的时候deliveryBlock的时候堆区的obj已经被释放。即:ARC下编译器在NSStackBlock类型的block传递过程中进行了自动优化。


为了进一步验证,我做了如下测试

- (void)viewDidLoad {
    [super viewDidLoad];
    [self test:^{
       NSLog(@"%@",self.object);
    }];
}
- (void)test:(void(^)(void))block {
    NSLog(@"%@",block); //log: <__NSStackBlock__: 0x7fff5ef49b88>
}

当object作为self的属性时,object在整个vc的生命周期存在,故不会有脱离调用栈的问题,所以编译器没有将其自动拷贝到堆。

推荐阅读更多精彩内容

  • 前言 Blocks是C语言的扩充功能,而Apple 在OS X Snow Leopard 和 iOS 4中引入了这...
    小人不才阅读 3,261评论 0 23
  • 一、Objective-C发展史 Objective-C从1983年诞生,已经走过了30多年的历程。随着时间的推移...
    没事蹦蹦阅读 5,416评论 12 34
  • 多线程、特别是NSOperation 和 GCD 的内部原理。运行时机制的原理和运用场景。SDWebImage的原...
    LZM轮回阅读 1,571评论 0 12
  • 当你奇怪他为什么对你忽冷忽热的时候他可能在为另一个人赴汤蹈火 ​​​
    疯viper阅读 54评论 0 0
  • 你在南方的艳阳里 大雪纷飞 我在北方的寒夜里 四季如春 若是你在南方里 找不到霓虹 我就在北极夜里 为你寻找极光 ...
    风玲依草阅读 86评论 4 4
  • 信念决定了思想和情绪,进一步决定了行动和人生的实相。作为一个母亲,我需要深深地反省我的言行举止,一直以来对女儿施加...
    helenliu258阅读 83评论 0 0
  • 本文为小马哥个人原创,如需转载请联系:QQ3348855313
    小马哥S阅读 228评论 0 0