Block的迴圈引用

2021-08-20 16:45:40 字數 2597 閱讀 4106

block的使用

1.概念:block實質就是乙個匿名函式塊,經過編譯器的編譯後,最終為乙個函式,block也是objective-c中的物件,根據block物件建立時所處的資料區不同而進行區別:

在棧上建立的block物件,_nsconcretestackblock

在堆上建立的block物件,_nsconcretemallocblock

在全域性資料區的block物件,_nsconcreteglobalblock

block可以擷取自動變數,所謂自動變數就是不是全域性或者靜態的變數,在當前上下文範圍內,block塊可以捕捉到它的乙個瞬間值,所謂瞬間值就是某一時刻的值,當我們在外面改變了變數的值,block內部仍然是之前某個瞬間的值,不會改變,譬如:

// 宣告乙個無返回值、無引數的block變數

​ __block int i = 10; // 如果block內部需要改變i的值,那麼這裡就應該給新增個__block,這時的變數成為__block變數

​ nsmutablearray *arr = [[nsmutablearray alloc] initwithobjects:@」1」,@」2」, nil];

​ nslog(@」arr count:%ld」,arr.count);

​ void (^blocktype)(void) = ^{

​ nslog(@」in block,i = %d」,i); // 這裡block截或了外部的自動變數,儲存了」瞬間值」

​ i = 100;

​ nslog(@」after change,i = %d」,i);

​ [arr removeobjectatindex:0];

​ i = 20;// 這裡改變i的值,看下block中是否會列印這個i為20,雖然這裡改變了i的值,但是外部的i是不會受到影響的

​ nslog(@」out block,i = %d」,i);

​ blocktype();

​ nslog(@」arr count:%ld」,arr.count);

block的儲存區域:

void (^blk)(void) = ^ {

​ nslog(@」global block」);

int main(int argc, const char * argv) {

​ @autoreleasepool {

// blockmanager *manager = [[blockmanager alloc] init];

// [manager statementparameter];

​ //列印的是nsglobalblock

​ blk();

​ nslog(@」%@」,[blk class]);

​ void (^blk1)(void) = ^ {

​ nslog(@」global block」);

​ // 沒有捕獲了自動變數,列印的是nsglobalblock

​ blk1();

​ nslog(@」%@」,[blk1 class]);

​ // 捕獲了自動變數,列印的是nsmallocblock

​ int i = 1;

​ void (^captureblock)(void) = ^{

​ nslog(@」capture:%d」,i);

​ captureblock();

​ nslog(@」%@」,[captureblock class]);

​ return 0;

block複製:

配置在棧上的block,如果其所屬的棧作用域結束,該block就會被廢棄,對於超出block作用域仍需使用block的情況,block提供了將block從棧上覆制到堆上的方法來解決這種問題,即便block棧作用域已結束,但被拷貝到堆上的block還可以繼續存在。

在arc有效時,大多數情況下編譯器會進行判斷,自動生成將block從棧上覆制到堆上的**,以下幾種情況棧上的block會自動複製到堆上

之前在棧上建立的block擷取了自動變數i,但是實際卻顯示的是nsmallocblock類,就是因為這個block物件賦值給了_strong修飾的變數captureblk(_strong是arc下物件的預設修飾符)

因為上面四條規則,在arc下其實很少見到_nsconcretestackblock類的block,大多數情況編譯器都保證了block是在堆上建立的

3.使用__block發生了什麼?

block捕獲的自動變數新增__block說明符,就可以在block內讀寫該變數,也可以在原來的棧上讀寫該變數.

__block保證了棧上和block內(通常在堆上)可以訪問和修改「同乙個變數」,__block是如何實現這一功能的?

__block發揮作用的原理:將棧上用__block修飾的自動變數封裝成乙個結構體,讓其在堆上建立,以方便從棧上或堆上訪問和修改同乙份資料。

參考:

block 迴圈引用

結論 block作為成員變數,內部引用self的成員變數,必須使用self 弱引用 block作為區域性變數,無論怎樣寫,都不會對self造成強引用 block為變數 1 block為成員變數 typedef nsstring blockcc void inte ce twoviewcontroll...

block迴圈引用

底層原始碼 typedef void ghblock void struct main block impl 0 static void main block func 0 struct main block impl 0 cself static void main block copy 0 st...

BLOCK迴圈引用

何時block才會迴圈引用 為什麼block會迴圈引用 我們很多行為會導致block的copy,而當block被copy時,會對block中用到的物件產生強引用 arc下 或者引用計數加一 mrc下 如下 property nonatomic,readwrite,copy completionblo...