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的生命周期存在,故不会有脱离调用栈的问题,所以编译器没有将其自动拷贝到堆。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,396评论 30 472
  • 前言 Blocks是C语言的扩充功能,而Apple 在OS X Snow Leopard 和 iOS 4中引入了这...
    小人不才阅读 9,153评论 0 23
  • Block 梳理与疑问 时隔一年,再次读 《Objective-C 高级编程》,看到 block 一章,这一次从头...
    DeerRun阅读 3,907评论 0 2
  • 一、Objective-C发展史 Objective-C从1983年诞生,已经走过了30多年的历程。随着时间的推移...
    没事蹦蹦阅读 11,131评论 12 34
  • 多线程、特别是NSOperation 和 GCD 的内部原理。运行时机制的原理和运用场景。SDWebImage的原...
    LZM轮回阅读 6,120评论 0 12

友情链接更多精彩内容