首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

iOS開發進階:深度解析Block捕獲變量的四種場景與內存語義

     編輯:關於C

Block在iOS開發中極常用,但許多開發者對其捕獲變量行為模糊不清。今天我們扒開Block真面目,從編譯器視角徹底講清四種變量捕獲場景。

核心結論先行

判斷Block能否跟蹤變量變化,關鍵看變量生命週期是否超出Block定義作用域。只需記住:「即將銷毀的變量按值捕獲,長期存活的變量按引用捕獲」,再加上__block特殊修飾。

場景一:普通局部變量 —— 值捕獲(快照)

void test() {
    int age = 10;
    void (^block)() = ^{
        NSLog(@"----age=%d", age);  // 捕獲定義時的值 10
    };
    age = 20;
    block();  // 輸出 10
}

編譯器視角等價代碼:

void test2() {
    int age = 10;
    void (^block)() = ^{
        NSLog(@"----age=%d", 10);  // 直接內嵌常量
    };
    age = 20;
    block();
}

原理:局部變量棧上分配,作用域結束即銷毀。Block定義時拷貝當前值(值捕獲),後續修改無關。這很安全,因為變量隨作用域消亡,捕獲快照避免懸空引用。

場景二:__block修飾變量 —— 引用捕獲(可讀寫)

void test3() {
    __block int age = 10;
    void (^block)() = ^{
        NSLog(@"----age=%d", age);  // 能跟蹤最新值
    };
    age = 20;
    block();  // 輸出 20
}

原理:__block將變量「包裝」到堆上(或特殊結構體),Block持有指向該包裝體的指針。變量生命週期延長,Block內可讀寫最新值,無論局部/全局。

場景三:static局部變量 —— 引用捕獲(全局存活)

void test4() {
    static int age = 10;
    void (^block)() = ^{
        NSLog(@"----age=%d", age);  // 動態訪問
    };
    age = 20;
    block();  // 輸出 20
}

原理:static變量存儲在全局數據區,程序運行期間永不銷毀。Block捕獲其地址,每次調用動態讀取最新值。

場景四:全局變量 —— 引用捕獲(天然長壽)

int num = 10;
void test5() {
    void (^block)() = ^{
        NSLog(@"----num=%d", num);
    };
    num = 20;
    block();  // 輸出 20
}

原理:全局變量同static,存儲於全局區,生命週期覆蓋整個程序。Block捕獲地址,實時訪問。

總結判斷表

變量類型存儲區生命週期Block捕獲方式能否跟蹤修改
普通局部棧作用域內值捕獲(拷貝)否
__block局部堆/包裝體延長至Block釋放引用捕獲(指針)是
static局部全局數據區程序全周期引用捕獲(地址)是
全局變量全局數據區程序全周期引用捕獲(地址)是

實戰判斷口訣

「只需判斷變量是否馬上銷毀:即將銷毀→值捕獲;長期存活→引用捕獲。特別注意__block強制延長壽命。」

掌握這四種場景,Block變量捕獲不再是迷,面試與實戰都能游刃有餘!

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved