block詳解

weixin_34107955發表於2016-08-18

block是蘋果為C語言的擴充套件的新功能,非標準功能,類似其他語言的閉包。block就是把可執行程式碼和程式碼中可以訪問的變數封裝起來。這些變數稱為捕獲的變數。

//block變數宣告的語法:返回值型別(^block變數名)(block引數列表)
//類似函式指標的宣告,可以省略引數名
   int(^testBlock)(int , id );

//block常量定義的語法:^返回值型別(引數列表){ 可執行程式碼};
//注意不能漏掉後面的分號(;)
 ^int(int a,id obj){
 
 NSLog(@"%d--%@",a,obj);

 };

block記憶體管理:MRC和ARC都只是管理堆上的物件。

MRC情況下:block可以存在棧上、堆上、全域性資料區
全域性資料區:只捕獲全域性變數或靜態變數或不捕獲任何變數,block就會存在全域性資料區(記憶體管理相關方法無效)

棧上:只要捕獲了自動變數(區域性變數)就會存在棧上(記憶體管理相關方法無效)

堆上:在棧上的block與區域性變數的生命週期一樣,所以有必要放到堆上管理,執行copy或Block_copy()可以將棧上的block複製到堆上。這個時候才能使用記憶體管理相關的方法。需要注意的是:copy和release或Block_copy()與Block_release()成對使用。還有就是隻有在棧上的block才能copy到堆上,對全域性資料區的block執行copy無效,引用計數加1。

ARC情況下:block只存在堆上、全域性資料區
全域性資料區:只捕獲全域性變數或靜態變數或不捕獲任何變數,block就會存在全域性資料區

堆上:只要捕獲了自動變數(區域性變數)就會存在堆上。不會存在棧上了,因為ARC能非常好的管理物件生命週期。

block只有捕獲的自動變數不能修改,因為block會複製捕獲的自動變數到block中,複製的自動變數相當於使用const修飾。如果自動變數是物件型別(引用型別)會將物件的引用計數加1,即保留物件。

如果想修改捕獲的自動變數,可以使用__block修飾:
MRC情況下:如果自動變數是物件型別,物件的引用計數不會加1,即不會保留物件。如果物件型別的自動變數釋放了,block中的程式碼可能會發生野指標錯誤,所以要確保物件型別的自動變數在block執行的時候沒有釋放(retain或者執行完blokc後再釋放)。這可以避免迴圈引用,能適應一些需要打破迴圈引用的情況。
ARC情況下:自動變數是物件型別,物件的引用計數仍然加1,即會retain物件。所以如果需要打破迴圈引用的話,還需要用__weak和__block一起來修飾物件型別的自動變數。

相關文章