Objective-C—— Block,objective-cblock

來源:互聯網
上載者:User

Objective-C—— Block,objective-cblock

OC Block 其實功能就類似C語言的函數指標,js中的閉包之類的。把代碼塊當做一個變數就行操作,有自己的變數和範圍。

簡單看一下Block的文法和可能出現的問題:

 

Block文法:

block文法相對寬鬆,很多部分都可以省略,常規上我們實現一個block需要有以下幾個部分

^ 傳回值類型 參數列表 運算式

例如

    ^int (int count){return count+1;};//傳回值為int 參數為int 運算式為 count+1;    ^void (void){NSLog(@"void");};    //傳回值為void 參數void 運算式為  NSLog(@"void");

可以看到文法相對簡單,而且傳回值類型可以省略那麼以上兩個block就變

    ^(int count){return count+1;};    ^(void){NSLog(@"void");};

如果不適用參數,那麼傳回值列表也可以省略

    ^(int count){return count+1;};    ^{NSLog(@"void");};

 

Block類型變數

Blcok類型的變數可以接受對應的Block,上例中兩個Block就需要以下兩種Block類型變數接收

    int (^intBlock)(int) = ^(int count){return count+1;};    void (^voidBlock)(void) = ^{NSLog(@"void");};

上例中,可以看到變數定義格式

傳回值類型 (^變數名稱) (傳回值類型)

如果嫌這種定義方式麻煩的話,可以使用typedef來簡化定義方式

    typedef int (^typedefBlock) (int);    typedefBlock block = ^(int count){return count+1;};

 

截獲變數值

Block中,可以使用調用Block之前的變數的值,例如

    int a = 5;    int (^intBlock)(int) = ^(int count){return count+a;};    NSLog(@"%d",intBlock(5));    2015-08-02 17:25:53.393 Dispatch[9970:3096937] 10

可以看到輸出結果是10,說明intBlock截獲了變數a的值。

但是如果我們想要修改a的值,就會出現錯誤可以自己嘗試一下。

想要修改需要在變數前添加__block修飾符,說明該變數在block中是可以被修改的。

    __block int a = 5;    int (^intBlock)(int) = ^(int count){a = 3; return count+a;};    NSLog(@"%d",intBlock(5));    2015-08-02 17:33:11.629 Dispatch[10118:3136172] 8

輸出結果為8,說明已經被我們修改了。

同樣的道理,對已OC對象來說也是,如果調用方法使用該變數可以,但是對變數進行賦值操作就需要加上__block修飾符。

 

Block循環參考

循環參考出現條件,該對象持有Block的成員屬性,同時在Block中使用self。這樣會造成Block和對象之間的相互引用,互相都無法釋放,形成記憶體泄露。

@interface ViewController (){    voidBlock _voidBlock;}- (void)viewDidLoad {    [super viewDidLoad];       // __block int a = 5;    _voidBlock = ^{NSLog(@"%@",self);};    _voidBlock();}

 這樣寫編譯去會提示我們self的強引用在Block中使用。

還有一種,如果我們在Block中使用了成員屬性,同樣會造成記憶體泄露。因為成員屬性是self指標指向的對象,還是在Block中持有了self。

 

__weak
為了避免這樣的情況發生,我們再上面的例子中稍微修改一下

- (void)viewDidLoad {    [super viewDidLoad];       // __block int a = 5;    __weak ViewController *temp = self;    _voidBlock = ^{NSLog(@"%@",temp);};    _voidBlock();}

使用弱引用對象就能很好的避免這種情況。

再有就是用__block也能夠避免迴圈。

- (void)viewDidLoad {    [super viewDidLoad];       // __block int a = 5;    __block ViewController *temp = self;    _voidBlock = ^{NSLog(@"%@",temp); temp = nil;};    _voidBlock();}

注意這樣寫必須調用該Block,執行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.