深入理解Block

2021-07-29 22:12:57 字數 2196 閱讀 3112

mac os x系統10.4及其ios 4.0後引入了閉包的概念,這項語言特性是作為擴充套件而加入gcc編譯器的。在foundation框架中大量使用了block。

塊就是乙個實現某個功能的函式閉包,這個函式閉包可以帶有引數,也可以沒有引數,可以有返回值也可以沒有返回值者,用符號』^』來表示。塊在宣告的範圍內,可以呼叫塊外部的全域性變數和區域性變數。

void (^someblock) () = ^

void (^block) (int a, bool b) = ^(int a, bool b)

int (^block2) (int a, bool b) = ^(int a, bool b)

需要主意的是,block內部不能改變外部變數,想要在block中改變變數的值,那麼我們只需要在變數宣告的時候加上__block修飾符。

__block int a = 0;

void (^block)() = ^;

每個object-c變數都佔據著某個記憶體區域,block本身也是乙個物件,在存放block物件的記憶體區域中,首個變數是指向class的指標isa,其餘記憶體裡包含著物件的其他所有資訊。

- isa 指標,所有物件都有該指標,用於實現物件相關的功能。

reserved,保留block函式**內的變數。

invoke,函式指標,指向具體的 block 實現的函式呼叫位址。在記憶體布局中最重要的就是invoke函式指標,指向block的實現**

descriptor,是指向結構體的指標,每個塊裡都包含此結構體。block將所捕獲的變數指標拷貝到descriptor變數後。表示 block 的附加描述資訊,主要是 size 大小,以及 copy 和 dispose 函式的指標。

variables,capture 過來的變數,block 能夠訪問它外部的區域性變數,就是因為將這些變數(或變 量的位址)複製到了結構體中。

對於 block 外的變數引用,block 預設是將其複製到其資料結構中來實現訪問的。對於用 __block 修飾的外部變數引用,block是複製其引用位址來實現訪問

定義block的時候,其所佔的記憶體區域是分配在棧中的。

在 objective-c 語言中,一共有 3 種型別的 block:

下面的這段**在執行的時候就很危險:

void (^block)();

int a = 3;

if (a > 0) ;

} else ;

}

在定義if else 語句中的兩個block都分配在棧記憶體區域,編譯器會給每個block分配好記憶體,然而等離開相應的範圍後,編譯器有可能會把分配給塊的記憶體覆蓋掉。於是這兩個塊只能保障在對應的if else語句範圍內有效,這樣的**執行起來就會出現問題。

為解決此問題,可以給block物件傳送copy訊息以拷貝到堆空間裡。一旦複製到堆上,block就成了帶引用計數器的物件了。後續的複製操作都不會真的執行複製,只是遞增塊物件的應用計數器。 以下**就是安全的:

void (^block)();

int a = 3;

if (a > 0) copy];

} else copy];

}

與全域性變數類似,全域性塊所使用的記憶體區域,在編譯期就已經完全確定了,全域性塊可以宣告在全域性記憶體裡。下面就是乙個簡單的全域性塊:

void (^block) () = ^
typedef  int (^blocksome) (bool flag, int value);

blocksome block = ^(bool flag, int value) ;

用塊引用及其所屬物件時,不要保留閉環,防止出現return cycle。如使用weakself來防止return cycle:

__weak  viewcontroller *wself = self;
定義乙個wself變數並加上__weak修飾符,在block**塊中,所有需要self的地方都用wself來替代。這樣就不會增加引用計數,所以block持有self物件也就不會造成迴圈引用,從而造成記憶體洩漏。

參考文章:

深入理解Block

mac os x系統10.4及其ios 4.0後引入了閉包的概念,這項語言特性是作為擴充套件而加入gcc編譯器的。在foundation框架中大量使用了block。塊就是乙個實現某個功能的函式閉包,這個函式閉包可以帶有引數,也可以沒有引數,可以有返回值也可以沒有返回值者,用符號 來表示。塊在宣告的範...

深入理解C語言 深入理解指標

關於指標,其是c語言的重點,c語言學的好壞,其實就是指標學的好壞。其實指標並不複雜,學習指標,要正確的理解指標。指標也是一種變數,占有記憶體空間,用來儲存記憶體位址 指標就是告訴編譯器,開闢4個位元組的儲存空間 32位系統 無論是幾級指標都是一樣的 p操作記憶體 在指標宣告時,號表示所宣告的變數為指...

mysql 索引深入理解 深入理解MySql的索引

為什麼索引能提高查詢速度 先從 mysql的基本儲存結構說起 mysql的基本儲存結構是頁 記錄都存在頁裡邊 各個資料頁可以組成乙個雙向鍊錶每個資料頁中的記錄又可以組成乙個單向鍊錶 每個資料頁都會為儲存在它裡邊兒的記錄生成乙個頁目錄,在通過主鍵查詢某條記錄的時候可以在頁目錄中使用二分法快速定位到對應...