宏定義不僅僅局限于一些簡單的常用固定標(biāo)記,對于可復(fù)用的的可移植的小功能性代碼阳液,也可以采用宏定義封裝誓酒,提高開發(fā)效率
本文通過一個(gè)實(shí)際例子引入主題
場景
在寫網(wǎng)絡(luò)請求的代碼時(shí),通常會做這樣一個(gè)處理嗅义,異步操作回調(diào)。這段代碼是通用的隐砸,所以可以利用宏定義抽取出來之碗,做可復(fù)用的封裝,下面通過代碼解讀季希。
代碼
#define within_main_thread(block,...)\
do {\
if ([[NSThread currentThread] isMainThread]) {\
if (block) {\
block(__VA_ARGS__);\
}\
} else {\
if (block) {\
dispatch_async(dispatch_get_main_queue(), ^{\
block(__VA_ARGS__);\
});\
}\
}\
} while (0);
分析
以上的代碼很簡單继控,大致的邏輯顯而易見,這里針對幾個(gè)地方進(jìn)行詳細(xì)分析:
-
within_mian_thread(block,...)
第一個(gè)參數(shù)是block
胖眷,第二個(gè)為可變參數(shù),在宏定義的實(shí)際代碼中可以發(fā)現(xiàn)為__VA_ARGS__
霹崎,并且被用作了block
的參數(shù)珊搀,這樣就增加了宏的可拓展性。 -
do{} while(0)
效果和不用它是一樣的尾菇,程序只執(zhí)行一次境析,使用它的目的是:將實(shí)際代碼包裝在了括號中,這樣在編譯時(shí)替換為實(shí)際代碼時(shí)就更加穩(wěn)定派诬。由這個(gè)目的我們還可以想到其他手段劳淆,例如@try{} @finally{}
,將代碼放在@finally
的括號中默赂。
實(shí)際使用
- (void)getData :(void (^)(NSString *, NSNumber *))complete {
// 從網(wǎng)絡(luò)獲取到兩個(gè)數(shù)據(jù)沛鸵,str和num
if (complete) {
within_main_thread(complete, str, num);
}
}
這里可能會有一個(gè)疑惑,從網(wǎng)絡(luò)獲取到的數(shù)據(jù)為何要在主線程中設(shè)置缆八,在異步線程中設(shè)置不也一樣嗎曲掰。這里的原因是考慮到安全性和封裝質(zhì)量,在主線程設(shè)置數(shù)據(jù)可以讓其他任何地方使用時(shí)不用關(guān)心數(shù)據(jù)的安全問題奈辰。