每個(gè)塊都具備其"固有類型"暴区,因而可將其賦給適當(dāng)類型的變量闯团。這個(gè)類型由塊所接受的參數(shù)及其返回值組成。
^(BOOL flag, int value){
if (flag) {
return value * 5;
} else {
return value * 10;
}
}
此塊接受兩個(gè)類型分別為BOOL及int的參數(shù)仙粱,并返回類型為int的值房交。如果想把它賦給變量,則需注意其類型伐割。變量類型及相關(guān)賦值語句如下:
int (^variableName)(BOOL flag, int value) = ^(BOOL flag, int value){
// Implementation
return someInt;
}
這個(gè)類型似乎和普通的類型大不相同候味,然而如果習(xí)慣函數(shù)指針的話,那么看上去就會覺得眼熟了隔心。塊類型的語法結(jié)構(gòu)如下:
return_type (^block_name)(parameters);
與其他類型的變量不同白群,在定義塊變量時(shí),要把變量名放在類型之中硬霍,而不要放在右側(cè)帜慢。這種語法非常難記,也非常難懂须尚。鑒于此崖堤,應(yīng)該為常用的塊類型起個(gè)別名,尤其是打算把代碼發(fā)布成API供他人使用時(shí)耐床,更應(yīng)這樣做密幔。開發(fā)者可以起個(gè)更為易讀的名字來表示塊的用途,而把塊的類型隱藏在其后面撩轰。
為了隱藏復(fù)雜的塊類型胯甩,需要用到C語言中名為"類型定義"(type definition)的特性。typedef關(guān)鍵字用于給類型起個(gè)已讀的別名堪嫂。比方說偎箫,想定義新類型,用以表示接受BOOL及int參數(shù)并返回int值的塊皆串,可通過下列語句來做:
typedef int(^EOCSomeBlock)(BOOL flag, int value);
聲明變量時(shí)淹办,要把名稱放在類型中間,并在前面加上"^"符號恶复,而定義新類型時(shí)也得這么做怜森。上面這條語句向系統(tǒng)中新增了一個(gè)名為EOCSomeBlock的類型速挑。此后,不用再以復(fù)雜的塊類型來創(chuàng)建變量了副硅,直接使用類型即可:
EOCSomeBlock block = ^(BOOL flag, int value) {
//Implementation
};
這樣代碼讀起來就順暢多了: 與定義其他變量時(shí)一樣姥宝,變量類型放在左邊,變量名放在右邊恐疲。
通過這項(xiàng)特性腊满,可以把使用塊的API做的更為易用些。類里面有些方法可能需要用塊來做參數(shù)培己,比如執(zhí)行異步任務(wù)時(shí)所用的"completion handler"(任務(wù)完成后所執(zhí)行的處理程序)參數(shù)就是塊碳蛋,凡遇到這種情況,都可以通過定義別名使代碼變得更為易讀漱凝。比方說疮蹦,類里有個(gè)方法可以啟動任務(wù),它接受一個(gè)塊作為處理程序茸炒,在完成任務(wù)之后執(zhí)行這個(gè)塊愕乎。若不定義別名,則方法簽名會像下面這樣:
- (void)startWithCompletionHandler:(void(^)(NSData *data, NSError *error))completion;
注意壁公,定義方法參數(shù)所用的塊類型語法感论,又和定義變量時(shí)不同,若能把方法簽名中的參數(shù)類型寫成一個(gè)詞紊册,那讀起來就順口多了比肄。于是,可以給參數(shù)類型起個(gè)別名囊陡,然后使用此名稱來定義:
typedef void(^EOCCompletionHandler)(NSData *data, NSError *error);
- (void)startWithCompletionHandler:(EOCCompletionHandler)completion;
使用類型定義還有個(gè)好處芳绩,就是當(dāng)你打算重構(gòu)塊的類型簽名時(shí)會很方便。比方說撞反,要給原來的completion handler塊再加一個(gè)參數(shù)妥色,用以表示完成任務(wù)所花的時(shí)間,那么只需修改類型定義語句即可:
typedef void(^EOCCompletionHandler)(NSData *data, NSTimeInterval duration, NSError *error);
修改之后遏片,凡是使用了這個(gè)類型定義的地方嘹害,比如方法簽名等處,都會無法編譯吮便,而且報(bào)的都是同一種錯(cuò)誤笔呀,于是開發(fā)者可據(jù)此逐個(gè)修復(fù)。若不用類型定義髓需,而直接寫塊類型许师,那么代碼中要修改的地方就更多了。開發(fā)者很容易忘掉其中一兩處,從而引發(fā)難于排查的bug枯跑。