OC __block

塊對象可以包含其訪問的自動變量的副本,但是這個變量是隻讀變量,當想要在多個塊對象之間共享變量,有三種方法:
(1)外部變量;
(2)靜態變量(static)
(3)若是在函數內部需要共享變量,需要將變量用__block修飾

注意:__block變量不能和static、auto、register同時指定。

下面舉例:

//
//  test.c
//  testClassCluster
//
//  Created by DH on 2016/11/16.
//  Copyright © 2016年 DH. All rights reserved.
//

#include "test.h"
#include <stdio.h>
#include <Block.h>

void (^g)(void) = NULL; //外部變量
int turn = 0;

void function(int n)
{
    __block int testBlock = 0; // 函數內部的快之間共享變量

    void (^b1)(void) = ^{ // 塊b1
        testBlock += 1;
        printf("%d:b1,n=%d,testBlock=%d\n",++turn,n,testBlock);
    };

    void (^b2)(void) = ^{ // 塊b2
        testBlock += 20;
        printf("%d:b2,n=%d,testBlock=%d\n",++turn,n,testBlock);
    };


    b1();
    b2();
    g = Block_copy(b1);
    testBlock += n * 1000;
    n = 999;
    b2();
}

int main(void)
{
    void (^myBlock)(void);

    function(1);
    myBlock = g;
    myBlock();
    function(2);
    myBlock();
    Block_release(g);
    Block_release(myBlock);

    return 0;
}

運行結果如下:
這裏寫圖片描述

下面進行說明:
我們從主函數開始看,void (^myBlock)(void)是聲明一個塊對象使用的變量,接着function(1)調用函數,傳入參數n=1。來到function函數,執行b1(),調用塊b1:

   void (^b1)(void) = ^{ // 塊b1
        testBlock += 1;
        printf("%d:b1,n=%d,testBlock=%d\n",++turn,n,testBlock);
    };

testBlock += 1後,testBlock的值爲1,n的值爲傳入的1,++turn是先加1,所以爲1,因此
第一行結果是1:b1,n=1,testBlock=1;
同理,執行b2(),調用:

void (^b2)(void) = ^{ // 塊b2
        testBlock += 20;
        printf("%d:b2,n=%d,testBlock=%d\n",++turn,n,testBlock);
    };

首選執行testBlock += 20。由於我們利用了__block對testBlock進行了修飾,所以b2可以共享testBlock.
因此,執行完這句後,testBlock的值變爲21。n依然是1,所以輸出爲2:b2,n=1,testBlock=21

接下來執行g = Block_copy(b1);
要理解這一句,首先要理解塊對象的複製,在函數內的塊對象的聲明週期和函數內聲明的變量一樣,當函數調用完畢就銷燬,同時這種塊對象的內存分配在棧上。如果我們不使用Block_copy()這個函數,直接g=b1,在函數function(1)執行完畢時,棧上的內存被回收,b1也就不存在了,而g還指向b1原來所在的內存,如有其它函數使用了這個內存,會造成難以預測的結果。而使用g = Block_copy(b1)則將b1複製到堆上面,從而解決了以上問題。
另外需要注意的是,這個時候調用塊複製函數,也會將這個時候塊中變量的值進行保存。而這個值是函數function(1)執行完畢後的值。

最後再執行函數最後一句b2(),得到結果3:b2,n=1,testBlock=1041,那麼第一次函數調用結束,這時要將最後的testBlock的值保存到堆上面。

接着回到主函數的調用:

myBlock = g;
myBlock();

輸出:
4:b1,n=1,testBlock=1042

後面的執行不再贅述,來到最後一句:myBlock();
它輸出的結果是:8:b1,n=1,testBlock=1043,
我們發現在第一次調用的時候的變調testBlock的值一直被保留下來了。

發佈了42 篇原創文章 · 獲贊 2 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章