Block的類型

前言

Block在iOS日常開發(fā)中極其常見,大家應(yīng)該幾乎都使用過,比較熟悉它的用法,而且知道Block可能引起循環(huán)引用,今天來聊聊Block,以及Block造成內(nèi)存泄露的根本原因。

Block是什么

首先,Block和普通實(shí)例一樣是是一個對象,他有自己的isa指針。
它就是一個里面存儲了指向定義代碼塊的函數(shù)指針和block外部上下文變量信息的結(jié)構(gòu)體。通過斷點(diǎn)我們看到block的isa指針,如下圖:

isa

我們發(fā)現(xiàn)block的類型其實(shí)是不同的,這是為什么接下來我們看看Block到底有哪些類型。

Block的類型

我們通過實(shí)際例子看看的各種類型的block

  • NSMallocBlock
- (void)NSMallocBlock {
    int tempInt = 1;
    void (^block)(void) = ^ {
        NSLog(@"----------%d----------\n\n",tempInt);
    };
    block();
    [self printBlockSuperClass:block];
}

結(jié)果:NSMallocBlock -> __NSMallocBlock -> NSBlock -> NSObject

  • NSStaticBlock
- (void)NSStaticBlock {
    int tempInt = 1;
    __weak void (^block)(void) = ^ {
        NSLog(@"----------%d----------\n\n",tempInt);
    };
    block();
    
    [self printBlockSuperClass:block];
}

結(jié)果:NSStackBlock -> __NSStackBlock -> NSBlock -> NSObject

  • NSGlobalBlock
- (void)NSGlobalBlock {
    void (^block)(int a) = ^ (int a){
        NSLog(@"----------%d----------\n\n",a);
    };
    block(1);
    
    [self printBlockSuperClass:block];
}

結(jié)果:NSGlobalBlock -> __NSGlobalBlock -> NSBlock -> NSObject

我們發(fā)現(xiàn):

  1. 當(dāng)沒有外部變量時,block為__NSMallocBlock,它由開發(fā)者創(chuàng)建,存儲在堆內(nèi)存上。
  2. 當(dāng)有__weak修飾時block為__NSStackBlock,存儲在棧區(qū)。
  3. 當(dāng)block有參數(shù)時(捕獲了外部變量時)block為__NSGlobalBlock,存儲在全局區(qū)。

屬性關(guān)鍵字和外部變量類型對Block內(nèi)存的影響

為了驗(yàn)證我們定義了三中關(guān)鍵字的block,分別有storng、weak、copy修飾:

@property (nonatomic, strong) TestBlock strongBlock;
@property (nonatomic, weak) TestBlock weakBlock;
@property (nonatomic, copy) TestBlock copyBlock;

驗(yàn)證方法如下:

int globalInt = 1000;//全局變量
static staticInt = 10000;//全局靜態(tài)變量

- (void)blockInMemory {
    static tempStaticInt = 100000;//局部靜態(tài)變量
    int normalInt = 20000;
    _strongBlock = ^(int tempInt) {
        NSLog(@"tempInt = %d", normalInt);
    };
    _weakBlock = ^(int tempInt) {
        NSLog(@"tempInt = %d", normalInt);
    };
    _copyBlock = ^(int tempInt) {
        NSLog(@"tempInt = %d", normalInt);
    };
    NSLog(@"\nstrongBlock:%@\n_weakBlock:%@\n_copyBlock:%@",object_getClass(_strongBlock),object_getClass(_weakBlock),object_getClass(_copyBlock));
}

分別打印不同變量類型(全局變量、全局靜態(tài)變量、局部靜態(tài)變量、局部變量)和屬性關(guān)鍵字下block的類型,我們可以得出如下結(jié)論:

  1. 沒有外部變量時,三種Block都是 __NSGlobalBlock__
  2. 有外部變量時,
    2.1 外部變量時全局變量、全局靜態(tài)變量、局部靜態(tài)變量時:__NSGlobalBlock__(全局區(qū))
    2.2 外部變量時普通外部變量:copy和strong修飾的Block是__NSMallocBlock__(堆區(qū));weak修飾的block是__NSStackBlock__(棧區(qū))

有普通外部變量的block是在棧區(qū)創(chuàng)建的,當(dāng)有copy和strong修飾符修飾的時,會把block從棧移到堆區(qū)。

ARC下使用copy和strong關(guān)鍵字修飾block是一樣的。

結(jié)語

本篇為Block系列的第一篇,由此,我們了解了三種不同類型Block,接下來會以源碼的方式深入了解block的底層實(shí)現(xiàn),我們下篇再見。
Demo工程

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

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

  • 在研究block的類型之前,首先我們要知道c類語言的程序編譯后在內(nèi)存中的分布(由高位向低位排序): 棧區(qū):局部變量...
    hanl001閱讀 858評論 0 1
  • 前言:追溯block的父類,看清其本質(zhì) 前面我們也說過,block本質(zhì)上就是一個OC對象。從上面的代碼打印結(jié)果,我...
    ychen3022閱讀 396評論 0 0
  • 前言 Blocks是C語言的擴(kuò)充功能,而Apple 在OS X Snow Leopard 和 iOS 4中引入了這...
    小人不才閱讀 3,881評論 0 23
  • 一、block本質(zhì)是個對象,涉及閉包的概念,用于封裝代碼 int (^block)(int a,int b) = ...
    Demonboy閱讀 370評論 0 0
  • 關(guān)于李鸻的博士答辨論文《英國國民醫(yī)療服務(wù)體系行政治理研究: 制度史的視角》之初見。 翻看了一兩章,這本論文,已超越...
    窗花閱讀 766評論 0 0

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