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...