ARC下NSStackBlock去哪了

我在 Objective-C中Block的類型 一文中說到MRC下有NSGlobalBlock、NSMallocBlock以及NSStackBlock三種類型的block,而ARC下是沒有NSStackBlock類型的,在這里對其進(jìn)行一個更正補(bǔ)充。


在RAC下,進(jìn)行如下測試:

    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>

我發(fā)現(xiàn),在直接打印block的時候,他的類型顯示的還是NSStackBlock。而我們將這個block進(jìn)行賦值之后,打印deliveryBlock的結(jié)果是NSMallocBlock類型。
也就是說,NSStackBlock類型在ARC下是存在,只是在對他進(jìn)行賦值的時候,編譯器將棧區(qū)的block拷貝到了堆區(qū)(賦值和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當(dāng)作方法參數(shù)傳遞到了另外一個方法,那么一旦deliveryBlock不在原來方法的調(diào)用棧,而新方法調(diào)用deliveryBlock的時機(jī)又不得而知,可能在新方法調(diào)用的時候deliveryBlock的時候堆區(qū)的obj已經(jīng)被釋放。即:ARC下編譯器在NSStackBlock類型的block傳遞過程中進(jìn)行了自動優(yōu)化。


為了進(jìn)一步驗證,我做了如下測試

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

當(dāng)object作為self的屬性時,object在整個vc的生命周期存在,故不會有脫離調(diào)用棧的問題,所以編譯器沒有將其自動拷貝到堆。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,210評論 30 471
  • 前言 Blocks是C語言的擴(kuò)充功能,而Apple 在OS X Snow Leopard 和 iOS 4中引入了這...
    小人不才閱讀 3,785評論 0 23
  • Block 梳理與疑問 時隔一年,再次讀 《Objective-C 高級編程》,看到 block 一章,這一次從頭...
    DeerRun閱讀 658評論 0 2
  • 一、Objective-C發(fā)展史 Objective-C從1983年誕生,已經(jīng)走過了30多年的歷程。隨著時間的推移...
    沒事蹦蹦閱讀 5,890評論 12 34
  • 多線程、特別是NSOperation 和 GCD 的內(nèi)部原理。運行時機(jī)制的原理和運用場景。SDWebImage的原...
    LZM輪回閱讀 2,035評論 0 12