深入學習block

2021-09-08 11:48:24 字數 3099 閱讀 8221

首先,什麼是block?block其實就是乙個**塊,把你想要執行的**封裝在這個**塊裡,等到需要的時候再去呼叫。那block是oc物件嗎?答案是肯定的。

做一道很簡單的關於block的測試題:

int (^testblock)

(int) = ^(int

num) ;

nslog(

@"%d

", testblock(testblock(testblock(3

))));

這道題是我公司面試題中的一道,來面試的都是至少兩年工作經驗的,但是很鬱悶,這道題絕大多數人寫的都是6。。正確結果為:3。

以下講解的內容均是arc環境下。

一、block的分類

1.nsstackblock:

特點:生命週期由系統控制,函式返回即銷毀

用到區域性變數、成員屬性\變數,且沒有強指標引用的block都是棧block

int (^testblock)

(int) = ^(int

num) ;

nslog(

@"%d

", testblock(testblock(testblock(3

))));

注意:不是沒有強指標(copy或strong)引用的block,就是棧block,也有可能是全域性block(下面會介紹什麼是全域性block)。

2.nsmallocblock:

特點:沒有強指標引用即銷毀,生命週期由程式設計師手動管理

棧block如果有強指標引用或copy修飾的成員屬性引用就會被拷貝到堆中,變成堆block

//

堆block

int j = 0

;

void(^mallocblock)() = ^;

nslog(

@"%@

",mallocblock);

//輸出結果 <__nsmallocblock__: 0x7f8cd351db80>

上面**也沒用看到strong 或 copy修飾符,但是為什麼會強引用的,因為在arc環境下,我們在宣告變數的時候,前面是會被預設加上 __strong 修飾符的。所以我們在arc下宣告的block一般都是堆block。

3.nsglobalblock: 

特點:命長,有多長?很長很長,人在塔在(應用程式在它就在)

沒有用到外界變數,或者只用到全域性變數、靜態(static)變數的block就是全域性block

對於全域性block,用weak,strong,還是copy修飾都是可以的。(但最好不用用weak)

//

全域性block

void (^globalblock) () = ^;

nslog(

@"%@

",globalblock);

//輸出結果 <__nsglobalblock__: 0x108152110>

注意:如果block中沒有用到外界變數,不管他是用什麼修飾符修飾,他都是全域性block!

例如:

void (^global2block) () = ^;

nslog(

@"%@

",global2block); //

輸出結果 <__nsglobalblock__: 0x1023a0150>

二、block對外界變數的捕獲

1.1 基本資料型別:區域性變數

block會拷貝該變數的值當做常量使用,外界修改變數的值不會影響block內部,且block內部不能對其修改

block內部修改外界變數i的值直接報錯,如果想要修改,可以在int a = 0前面加上關鍵字__block,此時i等效於全域性變數或靜態變數

int a = 0

;

void (^block1)() = ^;

a++;

block1();

//輸出結果 a = 0;

__block int b = 0

;

void (^block2) () = ^;

block2();

nslog(

@"b = %d

",b); //

輸出結果 b = 2;

1.2 

基本資料型別:成員變數(例項變數),靜態變數,全域性變數

block直接訪問變數位址,在block內部可以修改變數的值,並且外部變數被修改後,block內部也會跟著變

self.num = 1

;self.num ++;

void (^block3) () = ^;

block3();

nslog(

@"%d

",self.num);

//輸出結果為 3

2.1 

指標型別:區域性變數

block會複製乙份指標並強引用指標所指物件,且內部不能修改指標的指向,但是可以修改指標所指向物件的值

nsmutablestring *str = @"

abc"

.mutablecopy;

void (^block4) () = ^;

str = @"

123"

.mutablecopy;

block4();

//輸出結果為 "adbdef"

2.2 

指標型別:成員變數(例項變數),靜態變數,全域性變數

block不會複製指標,但是會強引用該物件,內部可修改指標指向,block會強引用成員屬性\變數所屬的物件,這也是為什麼block內部用到self.***或_***可能會引起迴圈引用的原因

static nsstring *staticstr = @"

abc"

;

void (^block5) () = ^;

staticstr = @"

123"

; block5();

//輸出結果為 staticstr = 123 staticstr = def

block深入學習

block的宣告和使用看上一節就行了。本章主要講block內部的實現過程及原理。block的定義和函式指標非常相似 對比一下 block定義 void someblock 函式指標定義 void functionpionter void functionname 當然區別還是有的,block的返回型...

UIApplication深入學習

新建乙個任意型別的ios應用工程,加入我們在class prefix輸入是tc,我們可以看到工程中生成乙個類 在main函式中,autoreleasepool 函式中 說明 當應用程式將要入非活動狀態執行,在此期間,應用程式不接收訊息或事件。比如來 了。說明 當應用程式入活動狀態執行,這個剛好跟上面...

深入學習CSS

什麼是css?在之前的這篇文章中已經介紹了初步的介紹,詳細請看 div加css進一步講解了css中的內容,先總結如下圖 其實在實際開發中,我們通常採用是外部樣式的匯入,這樣做的好處是對於很對有同樣設計樣式的頁面可以實現樣式的共享,這樣我們不僅僅可以節省了大量的時間,並且也方便我們可以靈活的呼叫的樣式...