想必大家對block都很熟悉了,雖然都會用,但是你真的知道它的原理嗎?比如為什麼要加上__block,這個修飾符到底有什麼用?不加會有什麼後果?block又是如何實現的等等。。。該篇文章就為大家揭曉關於block的實現原理~先給出問題,大家思考下結果吧,如果分別呼叫以下兩個方法,結果如何?
void blockfunc1()
; num = 200;
block();
}複製**
void blockfunc2()
; num = 200;
block();
}複製**
答案是
blockfunc1 : num equal 100
blockfunc2 : num equal 200
複製**
是不是有人答錯了?再來兩個函式。這兩個的結果與blockfunc2一樣,列印出來的 num 為 200
// 全域性變數
int num = 100;
void blockfunc3()
; num = 200;
block();
}複製**
void blockfunc4()
; num = 200;
block();
}複製**
疑問: 我們發現num做為區域性變數時加上 _ _block 修飾符、num做為全域性變數以及num為靜態區域性變數時在block中輸出結果是一樣的,皆為被修改之後的值,而做為區域性變數並且未加上__block的num在block中輸出的值卻還是未賦值之前的值。這是為什麼呢?探索這個問題我們就需要看看底層結構是如何實現的了objective-c是乙個全動態語言,它的一切都是基於runtime實現的!在執行時會將oc轉換成c,我們可以利用這個來檢視關於block在內部是如何實現的 新建乙個command line tool專案,將以上**放入main.m中,如圖
這裡我們開啟終端,cd到專案目錄下,然後將用下面的命令將oc重寫為c
clang -rewrite-objc main.m
複製**
這時我們可以發現當前目錄下多了乙個main.cpp檔案,開啟它並滾到最下面
這裡我們可以看到blockfunc1的c語言實現方法
void
blockfunc1
()複製**
去掉型別轉換
void
blockfunc1
()複製**
這裡我們可以看到
block實際上是指向結構體的指標該結構體為
我們來看下帶__block的blockfunc2
在 blockfunc1 中,block指向了乙個名為__blockfunc1_block_impl_0的結構體,並且在初始化時輸入了三個引數(__blockfunc1_block_impl_0最後的flags有預設引數,所以可以不用傳參),第三個引數就是我們寫的num,與blockfunc2相比較,這裡的num並沒有帶*號,所以說在這裡它只是傳值而非傳址,而下面的【num = 200;】也就沒什麼卵用了。這就是blockfunc2、blockfunc3與blockfunc4為什麼能列印出num改變後的值,而blockfunc1不行的原因。
在這裡我們也可以看出:
編譯器會將block的內部**生成對應的函式** so **
我們總結下,block在內部會作為乙個指向結構體的指標,當呼叫block的時候其實就是根據block對應的指標找到相應的函式,進而進行呼叫,並傳入自身我們再來看看 _ block, _block也被轉換成了結構體,並含有5個變數
struct __block_byref_num_0 ;
複製**
對應著blockfunc2中的
__block int num = 100;
複製**
當建立num並用__block修飾的時候,會初始化這五個變數 當我們執行
num = 200;
複製**
對應著
(num.__forwarding->num) = 200;
複製**
上面剛剛提到過 _ _forwarding是例項本身,即型別結構體__block_byref_num_0的&num,再找到對應的num變數,將其原來的100修改為200~~ iOS實現簡單的block的例子
oc中的block主要用來儲存一段 在需要的時候執行。下面是乙個小的例子 import viewcontroller.h inte ce viewcontroller myblock 定義乙個block property nonatomic,copy void myblock end impleme...
iOS 的 Block 的使用
block 是一種資料型別,用來存 用來儲存一段 想用 的時候就呼叫這段 使用場景 1.動畫 2.多執行緒 3.集合遍歷 4.網路請求 區別於函式 函式也是用來儲存一段 的,當呼叫函式的時候才會執行裡面的 但是函式不能在程式執行的時候再在指定的位置執行 1.沒引數也沒返回值的block void g...
block 塊的內部結構
每個oc物件都佔據著某個記憶體區域,因為例項變數的個數及物件所包含的關聯資料互不相同,所以每個物件所佔的記憶體區域大小也是有大有小,塊本身也是物件,在存放塊物件的記憶體區域中,首個變數是指向class物件的指標,該指標叫做isa。其餘記憶體裡含有塊丟向正常運轉所需的各種資訊。如下 塊 void is...