這段時間一直忙着開發,很久沒來博客了,人氣稀少了很多,準備持續更新一個專題,主要談談OC底層的一些實現機制,並會對一些經典的面試題進行分析,感興趣的能夠持續關注,第一講的主題是: BLock的實現和運用面試
咱們一塊兒來看看,經Clang編譯後的block結構以下:數組
1 struct Block_literal_1 { 2 void *isa; 3 int flags; 4 int reserved; 5 void (*invoke)(void *, ...); 6 struct Block_descriptor_1 { 7 unsigned long int reserved; 8 unsigned long int size; 9 // optional helper functions 10 void (*copy_helper)(void *dst, void *src); // IFF (1<<25) 11 void (*dispose_helper)(void *src); // IFF (1<<25) 12 // required ABI.2014.5.25 13 const char *signature; // IFF (1<<30) 14 } *descriptor; 15 // imported variables 16 };
能夠看到在Block結構體中含有isa指針,這就證實了Block其實就是對象,並具備通常對象的全部功能。這個isa指針被初始化爲_NSConcreteStackBlock
或者_NSConcreteGlobalBlock
類的地址。在沒有開啓ARC的狀況下,若是Block中包含有局部變量則isa被初始化爲前者,不然就被初始化爲後者。而當ARC開啓後,若是Block中包含有局部變量則isa被初始化爲_NSConcreteMallocBlock
,不然就被初始化爲_NSConcreteGlobalBlock
。invoke是一個函數指針,它指向的是Block被轉換成函數的地址。最後的imported variables部分是Block須要訪問的外部的局部變量,他們在編譯就會被拷貝到Block中,這樣一來Block就是成爲一個閉包了。多線程
1 int main(int argc, const char * argv[]) 2 { 3 4 @autoreleasepool { 5 int (^sum)(int, int) = ^(int a, int b){ 6 return a + b; 7 }; 8 int add = sum(4, 5); 9 NSLog(@"%d", add); 10 } 11 return 0; 12 }
1 int main(int argc, const char * argv[]) 2 { 3 4 @autoreleasepool { 5 int i = 0; 6 void (^myBlock)() = ^{ 7 NSLog(@"%d",i); 8 }; 9 i = 100; 10 myBlock(); 11 } 12 return 0; 13 } 14 15 運行結果: i = 0 16 17 int main(int argc, const char * argv[]) 18 { 19 20 @autoreleasepool { 21 __block int i = 0; 22 void (^myBlock)() = ^{ 23 NSLog(@"%d",i); 24 }; 25 i = 100; 26 myBlock(); 27 } 28 return 0; 29 } 30 31 32 運行結果: i=100
(二) clang編譯block封裝的語句,一窺其廬山真面目閉包
^{printf("OC is Good");}
編譯後:函數
struct __block_literal_1 { void *isa; int flags; int reserved; void (*invoke)(struct __block_literal_1 *); struct __block_descriptor_1 *descriptor; }; void __block_invoke_1(struct __block_literal_1 *_block) { printf("OC is Good"); } static struct __block_descriptor_1 { unsigned long int reserved; unsigned long int Block_size; } __block_descriptor_1 = { 0, sizeof(struct __block_literal_1), __block_invoke_1;}
咱們能夠觀察到:經過iSa指針,內容在編譯的時候就會被拷貝到block中,從而造成閉包. 先體會下底層實現,接下來將會重點介紹block在OC的中的常見應用場景,今天的知識點,一句話歸納:閉包就是可以讀取其它函數內部變量的函數.動畫