Block

blocks是C語(yǔ)言的擴(kuò)充功能。blocks是帶有自動(dòng)變量(局部變量)的匿名函數(shù)。

截獲自動(dòng)變量

    int main()
    {
        int dmy = 256;
        int val = 10;
        const char *fmt = "val = %d\\n";
        void (^blk)(void) = ^{
            printf(fmt,val);
        };
        
        val = 2;
        fmt = "These value were changed. val = %d\\n";
        
        blk();
        
        return 0;
    }

結(jié)果:val = 2

分析:block語(yǔ)法的表達(dá)式使用的是它之前聲明的自動(dòng)變量fmt和val。block表達(dá)式截獲所使用的自動(dòng)變量的值為瞬間值。因?yàn)閎lock表達(dá)式保存了自動(dòng)變量的值(截獲),所以在執(zhí)行block語(yǔ)法后,即使改寫(xiě)了block中使用的自動(dòng)變量的值也不會(huì)影響block執(zhí)行的結(jié)果。

需要在block中修改一個(gè)變量的值,需要使用\\block說(shuō)明符。

block的實(shí)質(zhì)

block實(shí)際上是作為極普通的C語(yǔ)言源代碼來(lái)處理的。通過(guò)支持block的編譯器,含有block語(yǔ)法的源代碼轉(zhuǎn)換為一般C語(yǔ)言編譯器能夠處理的源代碼,并作為極為普通的C語(yǔ)言代碼被編譯。

clang -rewrite-objc sourceFileName

通過(guò)這個(gè)命令可以將含有block語(yǔ)法的源代碼轉(zhuǎn)換為C++代碼。
通過(guò)觀察,Block轉(zhuǎn)換為Block的結(jié)構(gòu)體類(lèi)型的自動(dòng)變量,\_\block變量轉(zhuǎn)換為\\_block變量的結(jié)構(gòu)體類(lèi)型的自動(dòng)變量(即棧上生成的該結(jié)構(gòu)體的實(shí)例)。

表 1-1 Block與\_\_block變量的實(shí)質(zhì)

名稱(chēng) 實(shí)質(zhì)
Block 棧上Block的結(jié)構(gòu)體實(shí)例
__block變量 棧上__block變量的結(jié)構(gòu)體實(shí)例

表 1-2 Block的類(lèi)

類(lèi) 設(shè)置對(duì)象的存儲(chǔ)域
_NSConcreteStackBlock
_NSConcreteGlobalBlock 程序的數(shù)據(jù)區(qū)域(.data區(qū))
_NSConcreteMallocBlcok

Block為_(kāi)NSConcreteGlobalBlock類(lèi)對(duì)象的情況

  • 記述全局變量的地方有Block語(yǔ)法時(shí)
  • Block語(yǔ)法的表達(dá)式中不使用應(yīng)截獲的自動(dòng)變量時(shí)

除了以上兩種情況block語(yǔ)法生成的block為_(kāi)NSConcreteStackBlock類(lèi)對(duì)象,且設(shè)置在棧上。

將block配置在堆上的NSConcreteMallocBlock類(lèi)在何時(shí)使用呢?

block超出變量作用域可存在的原因是?

\
\block變量用結(jié)構(gòu)體成員變量\\_forwarding存在的原因是?

Blocks提供了將Block和\_\_block變量從棧上復(fù)制到堆上的方法,這樣,即使Block語(yǔ)法記述的變量作用域結(jié)束,堆上的Block還可以繼續(xù)存在。

那么什么時(shí)候棧上的Block會(huì)復(fù)制到堆呢?

  • 調(diào)用Block的copy實(shí)例方法時(shí)
  • Block作為函數(shù)返回值返回時(shí)
  • 將Block賦值給附有\(zhòng)_\_strong修飾符、id類(lèi)型的類(lèi)或Block類(lèi)型成員變量時(shí)
  • 在方法名中含有usingBlock的Cocoa框架方法或Grand Central Dispatch的API中傳遞Block時(shí)

堆上的Block被廢棄時(shí)會(huì)調(diào)用dispose函數(shù)。

只有調(diào)用Block_copy函數(shù)才能持有截獲的附有\(zhòng)\_strong修飾符的對(duì)象類(lèi)型的自動(dòng)變量值。當(dāng)需要在Block中使用對(duì)象類(lèi)型自動(dòng)變量時(shí),除以下情形,推薦調(diào)用Block的copy方法。

  • Block作為函數(shù)返回值返回時(shí)
  • 將Block賦值給附有\(zhòng)_\_strong修飾符、id類(lèi)型的類(lèi)或Block類(lèi)型成員變量時(shí)
  • 在方法名中含有usingBlock的Cocoa框架方法或Grand Central Dispatch的API中傳遞Block時(shí)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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