什么是block
Blocks是C語言的擴充功能豺瘤,可以用一句話來表示Blocks的擴充功能:帶有自動變量(局部變量)
的匿名函數(shù)
镜廉。
所謂匿名函數(shù)
就是不帶有名稱的函數(shù)
蜘腌。C語言的標準不允許存在這樣的函數(shù)舍沙。例如以下源碼:
int func (int count);
它聲明了名稱為func
的函數(shù)怎栽。下面的源碼中為了調(diào)用函數(shù),必須使用該函數(shù)的名稱func
阀捅。
int result = func(10);
如果像下面這樣胀瞪,使用函數(shù)指針
來代替直接調(diào)用函數(shù),那么似乎不用知道函數(shù)名也能夠使用該函數(shù)饲鄙。
int result = (*funcptr)(10);
但其實使用函數(shù)指針也仍需要知道函數(shù)名稱凄诞。
int (*funcptr)(int) = &func;
int result = (*funcptr)(10);
而通過Blocks圆雁,源代碼中就能夠使用匿名函數(shù)
,即不帶函數(shù)名稱的函數(shù)帆谍。對于程序員來說伪朽,命名占用了很大比重,函數(shù)名既忆,變量名驱负,方法名嗦玖,屬性名患雇,類名和框架名
等都必須具備,而能夠編寫不帶名稱的函數(shù)對于程序員來說相當(dāng)具有吸引力宇挫。
現(xiàn)在我們知道了匿名函數(shù)
的概念苛吱。那么帶有自動變量值
又是什么呢?我們先來回顧一下在C語言函數(shù)中可能使用的變量
器瘪。
自動變量(局部變量)
函數(shù)的參數(shù)
靜態(tài)變量(靜態(tài)局部變量)
靜態(tài)全局變量
全局變量
其中在函數(shù)的多次調(diào)用之間能夠傳遞值的變量有翠储,靜態(tài)變量(靜態(tài)局部變量)
,靜態(tài)全局變量
橡疼,全局變量
援所。
雖然這些變量的作用域不同
,但在整個程序當(dāng)中欣除,一個變量總保持在一個內(nèi)存區(qū)域
住拭。因此雖然多次調(diào)用函數(shù),但該變量值總保持不變历帚,在任何時候以任何狀態(tài)調(diào)用滔岳,使用的都是同樣的變量值。
C++和Objective-C
使用類可保持變量值且能夠多次持有該變量自身
挽牢。它會聲明持有成員變量
的類谱煤,由類生成的實例
或對象
保持該成員變量
的值。但是聲明并實現(xiàn)C++禽拔,Objective-C
的類增加了代碼的長度刘离。這時我們就要用到Blocks了。Blocks提供了類似由C++和Objective-C類
生成實例或?qū)ο?/code>來保持變量值的方法睹栖。
Block語法
完整形式的Block語法與一般的C語言函數(shù)定義相比寥闪,僅有兩點不同。沒有函數(shù)名磨淌,帶有“^”疲憋。Block語法的BN范式如下:
^
返回值類型
參數(shù)列表
表達式
例如以下形式:
^int (int count) {return count + 1}
Block的語法可以省略很多東西,我們可以省略其返回值
梁只,如果不使用參數(shù)
缚柳,我們也可以省略其參數(shù)列表
埃脏,返回值類型
以及參數(shù)列表
均被省略的Block語法應(yīng)該是最常見的記述方式。
Block類型變量
在Block語法下秋忙,可將Block語法
賦值給聲明為Block類型
的變量中彩掐,即源代碼中一旦使用Block語法
就相當(dāng)于生成了可賦值給Block類型
變量的“值”。Block中由Block語法生成的值
也被稱為“Block”灰追《掠模“Block”既指源代碼中的Block語法
,也指由Block語法所生成的值
弹澎。
int (^blk)(int) = ^int (int count) {return count + 1}
在日常開發(fā)中我們會經(jīng)常使用typedef
來聲明Block類型的變量
typedef void (^myTestBlock)(NSString *參數(shù)1,NSString *參數(shù)2);
調(diào)用
self.myTestBlock(參數(shù)1, 參數(shù)2);
取得回調(diào)
self.myTestBlock = ^(NSString *參數(shù)1, NSString *參數(shù)2) {
};
截獲自動變量值
我們之前已經(jīng)了解到了帶有自動變量(局部變量)
的匿名函數(shù)
中的匿名函數(shù)
朴下,那么帶有自動變量值
究竟是什么呢?其實它在Block中表現(xiàn)為“截獲自動變量值”苦蒿。實例如下:
- (void)testBlock{
int dmy = 256;
int val = 10;
void (^blk)(void) = ^{
NSLog(@"%d,%d",dmy,val);
};
val = 2;
blk();
}
Blocks中殴胧,Block表達式截獲
所使用的自動變量的值
,即保持該自動變量
的瞬間值
佩迟,所以在執(zhí)行Block語法后团滥,即使改寫
Block中使用的自動變量
的值也不會影響
Block執(zhí)行時自動變量
的值。
2018-10-19 15:26:20.873463+0800 testDemo[74354:1089050] 256,10
執(zhí)行結(jié)果并不是改寫后的值报强,在Block執(zhí)行時這些值被保存灸姊,從而在執(zhí)行塊時使用,這就是自動變量值的截獲秉溉。
_ _block說明符
實際上力惯,自動變量值截獲只能保存執(zhí)行Block語法瞬間的值。保存后就不能改寫該值坚嗜,我們嘗試改寫截獲的自動變量值夯膀,看看會出現(xiàn)什么結(jié)果。
int main(){
int val = 0;
void (^block)(void) = ^{
val = 1;
};
block();
printf("block");
return 0;
}
該段代碼會產(chǎn)生編譯錯誤苍蔬。
Variable is not assignable (missing __block type specifier)
若想在Block語法的表達式中
將值賦給在Block語法外聲明
的自動變量诱建,需要在該自動變量上附加__block
說明符。
int main(){
__block int val = 0;
void (^block)(void) = ^{
val = 1;
};
block();
printf("val = %d\n",val);
return 0;
}
執(zhí)行結(jié)果:
val = 1
總結(jié)
這一篇先講解了一些block的概念碟绑,規(guī)范俺猿,功能以及一些用法,下一篇將著重記錄Block的實現(xiàn)格仲,在深究其原理前先明白block的相關(guān)特性將對后續(xù)的學(xué)習(xí)有很大的幫助押袍。