iOS Block學(xué)習(xí)筆記(二) -- Block截獲與修改自動變量

Block捕獲自動變量的值

Block匿名函數(shù)又稱為帶自動變量值的匿名函數(shù), 前面我們已經(jīng)知道了匿名函數(shù), 而帶自動變量值如何理解?

我們知道函數(shù)中可以可能使用的變量如下:

1. 自動變量(局部變量)
2. 函數(shù)的參數(shù)
3. 靜態(tài)局部變量
4. 靜態(tài)全局變量
5. 全局變量

而在函數(shù)的多次執(zhí)行過程中, 能夠傳遞的變量有:

1. 靜態(tài)局部變量
2. 靜態(tài)全局變量
3. 全局變量

通常情況下,我們在OC/C++中可以保持變量值且使用類對象來保持變量,并且能夠多次持有該變量.

然而,Blocks提供了這種類似于類的保存變量值的方式,并且能夠多次持有該變量. 因此使用Block可以不用聲明類也無需使用全局變量/靜態(tài)變量,就能夠滿足這種條件.

如下代碼可以證明:

int main() {
    int dmy = 256;
    int val = 10;
    const char *fmt = "val = %d\n";
    void (^blk)(void) = ^ {printf(fmt, val);};

    val = 2;
    fmt = "These values were changed. val = %d\n";

    blk();

    return 0;
}

最后結(jié)果運(yùn)行結(jié)果答應(yīng): val = 10.

表示Block中可以截獲所使用的自動變量的值, 即保存自動變量在創(chuàng)建Block的瞬時值. 因為Block保存的是瞬時值, 在執(zhí)行Block語法以后,即使修改了自動變量的值,也不會影響B(tài)lock中捕獲的自動變量在Block運(yùn)行時候的值.

__block變量修飾符

前面,我們了解到Block能在執(zhí)行創(chuàng)建Block語法時,自動變量的瞬時值. 但是一旦截獲該瞬時值, 在Block代碼中是無法修改的, 編譯器會報錯.

int val = 0;
void (^blk)(void) = ^{ val = 1;}; // 編譯時,這里就會報錯.

但是如果被截獲的自動變量是OC類對象,也是無法修改該對象的值, 但是能夠操作該對象的成員變量.

id array = [[NSMutableArray alloc] init];
void (^blk)(void) = ^{ 
    [array appendObject:@(1)];// 不會報錯,可以正常運(yùn)行
    array = [[NSMutableArray alloc] init]; // 會報錯, 無法修改自動變量的值
};

OC提供__block修飾符,用于修飾自動變量,此時我們就能在Block語法中修改被截獲的自動變量值.

__block int val = 0;
void (^blk)(void) = ^{ val = 1;};// 因為val是__block修飾,因此可以修改
blk();
printf("val = %d\n", val);

該源碼執(zhí)行的結(jié)果是: val = 1. 對于對象類型的變量,也能使用__block進(jìn)行修飾

__block id array = [[NSMutableArray alloc] init];
void (^blk)(void) = ^{ 
    [array appendObject:@(1)];// 不會報錯,可以正常運(yùn)行
    array = [[NSMutableArray alloc] init]; // 不會報錯, 可以修改__block自動變量的值
};
blk();

注意Block并沒有實現(xiàn)對C預(yù)言數(shù)組的截獲:

const char text[] = "hello";
void (^blk)(void) = ^ {
    printf("%c\n", text[2]); //這里會出錯, 因為Block并沒有實現(xiàn)對C預(yù)言數(shù)組的截獲
}

我們一般使用指針來規(guī)避該問題:

const char *text = "hello";
void (^blk)(void) = ^ {
    printf("%c\n", text[2]); //Block可以截獲指針變量(但是無法截獲C語言數(shù)組變量)
}

參考資料

  1. <<Objective-C 高級編程: iOS與OSX多線程和內(nèi)存管理>>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容