iOS開發-Block簡介

來源:互聯網
上載者:User

標籤:

Block簡稱閉包,實際上就是一個程式塊,Block的名稱類似於函數的入口地址,有自己的範圍範圍,在範圍結束接受後被銷毀(通常函數結束後),通常被分配在棧中(以便訪問局部變數和提高效能),Block本身是一個objective-c 中的對象,適用於記憶體管理方法,我們可以使用Block來完成一些同步執行的程式片段,封裝一些小型的工作和完成一項工作時的回調(callback)。Blocks 作為傳統回呼函數的一個實用的替代辦法,有以下兩個原因: 

1.它們可以讓你在調用的地方編寫代碼實現後面將要執行的操作。 因此 Blocks 通常作為架構方法的參數。 

2.它們允許你訪問局部變數。而不是需要使用一個你想要執行操作時整合所有內容相關的資訊的資料結構來進行回調,你可以直接簡 單的訪問局部變數。

1.Block的常用寫法

1.聲明一個block和它的實現

void (^my_block)(void)=^(void){

NSLog("my block");

}

my_block();

2.可以定義一個Block類型

typedef void(^my_block_type)(void)

my_block_type my_block = ^(void){

NSLog("my block");

}

 

2.Block對變數的訪問

預設情況情況下block使用到的局部變數都會被複製,而不是保留.所以它無法改變局部變數的值.

      如果在變數面前加上__block, 那麼編譯器不會複製變數, 而是去找變數的地址, 通過地址來訪問變數, 實際上就是直接操作變數.     另外塊是在棧上分配的, 所以一旦離開範圍, 就會釋放, 因此如果你要把快用在別的地方, 必須要複製一份.     所以在屬性定義一個快的時候需要使用copy:  @property (nonatomic, copy) void (^my_block_type)(void);     塊是不能保留的, retain對塊沒有意義.

 

3.Block在底層實現就是一個結構體資料結構。

 

對應的結構體定義如下:

 

 

struct Block_descriptor {

 

 

    unsigned long int reserved;

 

 

    unsigned long int size;

 

 

    void (*copy)(void *dst, void *src);

 

 

    void (*dispose)(void *);

 

 

};

 

 

struct Block_layout {

 

 

    void *isa;

 

 

    int flags;

 

 

    int reserved;

 

 

    void (*invoke)(void *, ...);

 

 

    struct Block_descriptor *descriptor;

 

 

    /* Imported variables. */

 

 

};

 


通過該圖,我們可以知道,一個block執行個體實際上由6部分構成:

1.isa指標,所有對象都有該指標,用於實現對象相關的功能。

2.flags,用於按bit位表示一些block的附加資訊,本文後面介紹block copy的實現代碼可以看到對該變數的使用。

3.reserved,保留變數。

4.invoke,函數指標,指向具體的block實現的函數調用地址。

5.descriptor, 表示該block的附加描述資訊,主要是size大小,以及copy和dispose函數的指標。

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

 

4.ARC和非ARC中block的區別:

 

ARC下Block何時會從棧自動被複製到推, 以及__block和__weak的使用問題

由於Block是預設建立在棧上, 所以如果離開方法範圍, Block就會被丟棄, 在非ARC情況下, 我們要返回一個Block ,需要 [Block copy];

在ARC下, 以下幾種情況, Block會自動被從棧複製到堆:

1.被執行copy方法

2.作為方法傳回值

3.將Block賦值給附有__strong修飾符的id類型的類或者Blcok類型成員變數時

4.在方法名中含有usingBlock的Cocoa架構方法或者GDC的API中傳遞的時候.

對於非ARC下, 為了防止循環參考, 我們使用__block來修飾在Block中實用的對象:

__block id blockSelf=self;

self.blk=^{

NSLog(@"%@",blockSelf);  //在非ARC下對於棧上的_block對象, Block不會對其複製, 僅僅使用, 不會增加引用計數.

};

對於ARC下, 為了防止循環參考, 我們使用__weak來修飾在Block中實用的對象:

__weak id weakSelf=self;

self.blk=^{

NSLog(@"%@",weakSelf);

};

 

iOS開發-Block簡介

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.