ARC下NSStackBlock去哪了

我在 Objective-C中Block的類型 一文中說到MRC下有NSGlobalBlock、NSMallocBlock以及NSStackBlock三種類型的block,而ARC下是沒有NSStackBlock類型的,在這里對(duì)其進(jìn)行一個(gè)更正補(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的時(shí)候,他的類型顯示的還是NSStackBlock。而我們將這個(gè)block進(jìn)行賦值之后,打印deliveryBlock的結(jié)果是NSMallocBlock類型。
也就是說,NSStackBlock類型在ARC下是存在,只是在對(duì)他進(jìn)行賦值的時(shí)候,編譯器將棧區(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ù)傳遞到了另外一個(gè)方法,那么一旦deliveryBlock不在原來方法的調(diào)用棧,而新方法調(diào)用deliveryBlock的時(shí)機(jī)又不得而知,可能在新方法調(diào)用的時(shí)候deliveryBlock的時(shí)候堆區(qū)的obj已經(jīng)被釋放。即:ARC下編譯器在NSStackBlock類型的block傳遞過程中進(jìn)行了自動(dòng)優(yōu)化。


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

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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

友情鏈接更多精彩內(nèi)容