Block詳解

block的定義,調(diào)用等就不介紹了,自行去查資料。

本文介紹內(nèi)容:

1.block的底層數(shù)據(jù)結(jié)構(gòu)

2.block的類型

3.block回調(diào)中使用參數(shù)傳遞數(shù)據(jù)

4.__block講解

5.block的循環(huán)引用問題

6.block與delegate區(qū)別


一.block的底層數(shù)據(jù)結(jié)構(gòu)

???????? clang編譯器的命令 :clang -rewrite-objc xxxxxx.m,這個命令用于clang重寫.m文件為.cpp文件可以查看block的底層數(shù)據(jù)結(jié)構(gòu)。

對應(yīng)的結(jié)構(gòu)體定義如下:

block的結(jié)構(gòu)

1.isa指針,所有對象都有該指針;

2.flags,用于按bit用于按 bit 位表示一些 block 的附加信息,本文后面介紹 block copy 的實現(xiàn)代碼可以看到對該變量的使用;

3.reserved,保留變量;

4.invoke,函數(shù)指針,指向具體的 block 實現(xiàn)的函數(shù)調(diào)用地址;

5.descriptor, 表示該 block 的附加描述信息,主要是 size 大小,以及 copy 和 dispose 函數(shù)的指針;

6.variables,capture 過來的變量,block 能夠訪問它外部的局部變量,就是因為將這些變量(或變量的地址)復(fù)制到了結(jié)構(gòu)體中。


二.block的類型

在 OC 語言中,一共有 3 種類型的 block:

1._NSConcreteGlobalBlock: 全局的靜態(tài) block

?????? 1.1 .? block被定義在函數(shù)以外,那么在ARC環(huán)境下就是創(chuàng)建一個全局block。全局block存儲在全局內(nèi)存中,不需要在每次調(diào)用的時候都在棧中創(chuàng)建,塊所使用的整個內(nèi)存區(qū)在編譯期已經(jīng)確定了,因此這種塊是一種單例,不需要多次創(chuàng)建。如圖示

???????? 1.2.在函數(shù)內(nèi)部如果block不捕獲外部變量,也是全局block類型。如圖所示



? 2._NSConcreteStackBlock? 保存在棧中的 block,當(dāng)函數(shù)返回時會被銷毀

??????? 2.1 在MRC環(huán)境下,默認(rèn)創(chuàng)建棧區(qū)block,一般使用copy函數(shù)拷貝到堆區(qū)再使用,否則block可能會被釋放,在ARC環(huán)境下一般不考慮。

???? ?? 2.2 在ARC環(huán)境下,當(dāng)需要捕獲外部變量時其實如果我們僅僅創(chuàng)建block,這個block時_NSConcreteStackBlock類型的,如圖示:

??????????????? 注意:但是,一旦我們使用一個該類型的block對象p(strong修飾的對象)來指向這個定義的block時,系統(tǒng)會主動對其進(jìn)行copy到堆區(qū)再使用,所以我們在打印p對象時看到的是_NSConcreteMallocBlock類型,而不是_NSConcreteStackBlock了,如圖示:




?? 3._NSConcreteMallocBlock 保存在堆中的 block,當(dāng)引用計數(shù)為 0 時會被銷毀。

???????? 堆block其實就是棧block剛剛提到的兩種形式。在MRC的模式下需要手動將其copy到堆上,NSMallocBlock支持retain、release,會對其引用計數(shù)+1或-1,copy不會生成新的對象,只是增加了一次引用,類似retain;而在ARC模式下會自動對其進(jìn)行copy,不需要自己手動去管理,盡可能使用ARC。



三.block回調(diào)中使用參數(shù)傳遞數(shù)據(jù)(此處不講解使用block進(jìn)行回調(diào))

??????? 前面我們一直提到block內(nèi)部捕獲外部變量,由于是否捕獲外部變量導(dǎo)致了block所分配的內(nèi)存區(qū)域也不一樣,那么我們不通過捕獲變量,而是通過參數(shù)傳遞的方式,又會如何呢?

?????? 1.經(jīng)測試首先可以確定的是這個block類型還是全局block

?????? 2.參數(shù)傳遞遵循“值傳遞”,所謂“值傳遞”就是:如果傳遞的參數(shù)是基本數(shù)據(jù)類型,就是具體的數(shù)值,無論形參如何改變,實參是不會改變的;如果傳遞的是指針類型,那么形參也會指向?qū)崊⑺赶虻膬?nèi)存地址,所以當(dāng)形參改變指向的內(nèi)存地址的內(nèi)容后,實參所指向的內(nèi)存地址的內(nèi)存也就發(fā)生了變化;但是如果改變形參指向的內(nèi)存地址(改地址,相當(dāng)于形參又指向了一片新的內(nèi)存地址),那么實參肯定不會變。

示例1:

參數(shù)為基本數(shù)據(jù)類型



示例2:

參數(shù)為不可變類型


示例3:

參數(shù)為可變類型



四.__block講解

未完待續(xù)。。。

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

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

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