先來簡單介紹一下block
block是什麼?蘋果推薦的型別,效率高,在執行中儲存**。用來封裝和儲存**,有點像函式,block可以在任何時候執行。
block和函式的相似性:(1)可以儲存**(2)有返回值(3)有形參(4)呼叫方式一樣。
定義乙個簡單的block
我們再給a賦值為20,此時列印出來a 的值還是10
但當我們在第一次給a 賦值時,前面加上__block 的時候,則列印出來20。
那麼為什麼加上__block 後 就列印出20了呢,這個原理是什麼呢?
此時開啟當前的.cpp 檔案(會有差不多10萬行**),前面我們都忽略,只需要滾動到最後,此時你會發現block跟oc中的變化。
接下來我們乙個個來看這個block,先來看等號左邊的。
void(*block)()
這是乙個沒有引數沒有返回值的函式指標,既然是乙個函式指標,那它就是乙個變數,變數裡面只能儲存函式位址,然後它又在等號的左邊是不是意味著右邊返回的是乙個函式位址(自己推斷)。
再看等號右邊:
接下來,又重新給 a賦值為 20,但是block 最終要找到 funcptr 裡面存放的是值來執行, 在這裡才會最終執行列印a 的值的**,但是這段**裡 a 是 10 了。所以最終列印的還是10。
最後可以概括為block 底層實現 分兩種:剛剛上面的就是第一種(不加__block), 會建立乙個結構體,實現構造方法,來接收三個引數。
接下來看加上__block 的實現。
修改我們的**:
再次在終端裡面進行編譯,你會發現生成的結構體會變化。
等號左邊會封裝乙個__block_byref_a_0 結構體型別的變數a,下面是結構體的宣告:
truct __block_byref_a_0 ;
等號右邊:
;
這裡僅僅是建立,因為使用了__block 所以建立了乙個block 型別的結構體,接下來會才是呼叫block,你會發現其餘引數和第一種實現都一樣,唯一不同的是再去取值的時候,拿到的是結構體的位址,只要把位址傳遞過去,就有了最高的操作許可權,到時候再去取值就可以取到記憶體中最新的值。
接下來(a.__forwarding->a) = 20;這句**是拿到結構體裡面的位址去修改a的值為20。
後面再去列印,列印的就是記憶體位址中最新的值,所以就是20。
Block底層實現
步驟一 建立乙個控制台應用,在main中新增塊的測試 import int main int argc,const char ar testblock return 0 步驟二 開啟終端,定位到main.m檔案目錄,錄入xcode命令 xcrun sdk iphoneos clang arch ar...
OC底層 block型別
block繼承自nsblock,nsblock繼承自nsobject 分為三種 怎麼樣建立三種block?void test void test 如下圖 呼叫了auto遍歷的block呼叫了copy時,就會生成 nsmallocblock型別的block,這是將放在棧中的block放進了堆記憶體中,...
ConcurrentHashMap底層實現
concurrenthashmap融合了hashtable和hashmap二者的優勢 hashtable是做了同步的,hashmap沒有同步,所以hashmap在單執行緒情況下效率高,hashtable在多執行緒情況下,同步操作能保證程式執行的正確性 但是hashtable每次同步執行都要鎖住整個結...