1诉植、什么是Block
帶有自動(dòng)變量(局部變量)的匿名函數(shù)昵观。
Block實(shí)質(zhì)就是Objective-C對(duì)象晾腔。
2灼擂、Block語(yǔ)法
^【返回值類型】【參數(shù)列表】【表達(dá)式】
exp. ^int (int count) {return count + 1;}
注意:【返回值類型】和【參數(shù)列表】可省略
3、Block類型變量
exp.
{
int (^blk)(int) = ^int (int count) {return count + 1;}
blk(1);
}
{
typedef int (^blk_t)(int);
blk_t blk = ^int (int count) {return count + 1;}
blk(1);
}
4觉至、截獲自動(dòng)變量值
int main() {
int val = 10;
const char *str = "val = %d\n";
void (^blk)(void) = ^{printf(str, val);};
val = 2;
str = "new val = %d\n";
blk();
return 0;
}
輸出結(jié)果:val = 10;
分析:block截獲自動(dòng)變量val和str的瞬時(shí)值剔应,并保存在自己的結(jié)構(gòu)體中,block外部再改變自動(dòng)變量的值不影響block自身保存的值康谆。
5领斥、__block說明符
自動(dòng)變量截獲只能保存瞬時(shí)值,保存后就不能改寫沃暗,當(dāng)嘗試在Block中改寫截獲的自動(dòng)變量值,就會(huì)報(bào)錯(cuò)何恶。
但是孽锥,用__block修飾自動(dòng)變量后,就可在Block中改寫了细层。
6惜辑、Block實(shí)質(zhì)
Block實(shí)質(zhì)就是Objective-C對(duì)象。并且Block的類有以下三種:
①_NSConcreteStackBlock(棧)
②_NSConcreteGlobalBlock(程序的數(shù)據(jù)區(qū)域(.data區(qū)))
③_NSConcreteMallocBlock(堆)
生成的Block為_NSConcreteGlobalBlock類對(duì)象的兩種情況:
1.在定義全局變量的地方使用Block語(yǔ)法時(shí)疫赎。
2.Block語(yǔ)法的表達(dá)式中不使用截獲的自動(dòng)變量時(shí)盛撑。
且設(shè)置在程序的數(shù)據(jù)區(qū)域中。
除了上面的兩種情況捧搞,Block語(yǔ)法生成的Block為_NSConcreteStackBlock類對(duì)象抵卫,且設(shè)置在棧上狮荔。
設(shè)置在全局變量上的Block即使在變量作用域外也可以用指針安全地訪問,但是設(shè)置在棧上的Block當(dāng)其所屬的變量作用域結(jié)束時(shí)就會(huì)被廢棄介粘,無(wú)法再訪問殖氏。
解決方法:將Block從棧上復(fù)制到堆上。
在ARC開啟時(shí)姻采,以下四種情況系統(tǒng)會(huì)自動(dòng)將Block從棧上復(fù)制到堆上雅采。
1.將Block作為函數(shù)返回值。
2.向方法或函數(shù)的參數(shù)中傳遞Block慨亲。
3.將Block賦值給附有__strong修飾符id類型的類或Block類型成員變量婚瓜。
4.Cocoa框架的方法且方法名中含有usingBlock或GCD的API。
其他情況需要手動(dòng)復(fù)制刑棵。
不同情況調(diào)用copy的效果:
1._NSConcreteStackBlock→copy→從棧復(fù)制到堆
2._NSConcreteGlobalBlock→copy→什么也不做
3._NSConcreteMallocBlock→copy→引用計(jì)數(shù)增加
注意:不管Block配置在何處巴刻,用copy方法復(fù)制不會(huì)有任何問題,在不確定時(shí)調(diào)用copy即可铐望。
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者