Objective-C 基礎之— Block本質+源碼剖析
block 又稱之為“自帶變量的匿名函數”,拋開OC語法定義block的形式不談,其實好多語言都有類似的函數,比如JS的回調函數(其實就是將一個匿名還是作為函數的實參)、swift的閉包等等。。
首先講一下oc block的實質,通過自身的理解,加以各位大神的剖析文章。block 在編譯時期會被編譯成結構體,也就是說OC的block底層是使用C語言結構體實現的, 和對象、類的實現是一樣的(所以其實block就是OC中的一個對象),這個結構體包括兩個結構體成員變量和一個構造函數,我們都知道Objective-C是用OC實現底層的,所以我們需要將代碼轉化為底層的實現(使用Clang -rewrite-objc [文件名], 這個命令是將OC語言轉化成C或者C++的代碼,經常使用這個命令我們窺探OC的底層奧秘)
上面的源碼轉換成C代碼之後,我做了一次完全的剖析,我們可以得出的結論就是,block 的實現其實就是一個結構體,而其的調用則是調用結構體內的函數指針調用函數;下面我將稍微改動一下代碼,看一下生成的底層代碼,研究一下,截獲的外部變量的情況:
我只將不同的代碼提出來 .m源代碼 int main(int argc, char * argv[]) { int a = 10; void (^myBlock)(void) = ^{ NSLog(@"hello world %d", a); }; myBlock(); return 0; } clang 轉換C代碼 // 我們看出來了這個時候__main_block_func_0的結構體的構造函數,多傳了一個變量a的參數,我們看到,並沒有把a的變量指針傳遞,而是將變量的值傳遞 int main(int argc, char * argv[]) { int a = 10; void (*myBlock)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, a)); ((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock); return 0; } // block 函數執行體當然也會變了,生成了一個變量,這個變量是__main_block_impl_0結構體裏的變量a static void __main_block_func_0(struct __main_block_impl_0 *__cself) { int a = __cself->a; // bound by copy NSLog((NSString *)&__NSConstantStringImpl__var_folders_dr_jkts5c395zs9xcx0bt_r7fx40000gn_T_main_3e8c5a_mi_0, a); } // 重要的結構體來了,這個結構體內生成了一個成員變量a struct __main_block_impl_0 { struct __block_impl impl; struct __main_block_desc_0* Desc; int a; __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _a, int flags=0) : a(_a) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } };那麽我們可以看出,再沒有任何修飾符的情況下,block截獲的變量只是一個值,而並不是指針,所以,內部執行函數無法改變block外部的變量
通過上邊的例子,我們可以猜想,如果block的結構體如果可以擁有變量的指針那麽,就可以修改外部變量的值了 ,所以 _ block就是做這件事情的,其實_ block的實現遠比我們想象的復雜,我們看一下__block 修飾之後轉換的代碼:
所以我們可以看得出來_ block 的作用是生成外部變量的指針,從而達到在block內部可以修改的目的;下一篇文章將會結合這篇文章Block的本質,總結_ weak _ block _ strong的使用。
致謝:https://blog.csdn.net/abc649395594/article/details/47086751
https://www.jianshu.com/p/fdd7fa9a9e7e
兩篇文章的對我的幫助!
Objective-C 基礎之— Block本質+源碼剖析