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í)