block的一些概念什麼的就不說了,主要記錄一下,block是怎麼實現的。函數
在main.m中寫了一個blockspa
用 clang -rewrite-objc main.m 會生成一個main.cpp 文件,是C++代碼,其實就是用到了C++的結構體,熟悉一些C++的結構體語法就能看懂了。(這個cpp文件中代碼炒雞多,只要看關於Block的就好了,以下圖)指針
這個block結構體就是咱們平時用的block 的本質,它由 兩個結構體變量 和 一個結構體構造方法組成內存
main函數中 紅色框是block的建立.源碼
拆開看就是調用了block結構體的構造方法: __main_block_impl_0() it
,這個構造方法須要傳入3個參數:1.void *fp 2.desc(計算保存block的大小) 3.flags = 0(flags 系統默認傳0)變量
對於 void *fp(fp是能夠指向任何類型的指針變量)。原理
咱們看源碼,它是傳入了(void *)__main_block_func_0 爲何這麼寫呢?由於函數名能夠表明一個函數在內存中的首地址,void *fp 能夠指向任何類型,固然也能夠指向函數類型, 又函數名能夠表明首地址,因此這裏直接傳函數名就能夠,其實不寫前面的強制轉換(void *) 也是能夠的。語法
而且這個fp 被賦值給 block結構體中的,成員結構體__block_impl 中的成員 void *FuncPtr方法
下面咱們拆開看這個紅色框的代碼:
到此就完成了block的建立。
去掉強制轉換的部分:
代碼的意思是:經過指針變量找到那個建立的block(結構體) 取block(結構體) 裏面的impl結構體 的成員 FuncPtr 所指向的方法(即:咱們寫在block塊中的方法) 並執行方法。
就是調用下面這個方法,執行 printf("哈哈")。 其中 __cself 指向 Block值,Block做爲參數進行了傳遞。
static void __main_block_func_0( struct __main_block_impl_0 *__cself ) {
printf("哈哈");
}
clang 後的代碼:
能夠看到block結構體中多了一個 int a;看上圖,能夠知道block將這個a存儲在int a變量中了
執行block分析:
__cself->a 取出block結構體中的a變量值 ,而後打印輸出。
如今明白了block捕獲自動變量的原理了吧!