多用枚舉塊,少用 for 循環(huán)
在編程中經(jīng)常需要列舉 collection 中的元素,當(dāng)前 OC 語言有多種方法實現(xiàn)此功能, 可以用標(biāo)準(zhǔn)的 C語言 循環(huán),也可以用 OC 1.0 的 NSEnumerator 以及 OC 2.0 的快速便利 (fast enumeration),
引入'塊'這一特性后, 又多出來幾種新的便利方法,而這幾種方式容易為開發(fā)者所忽視,采用這個幾種新方法便利 collection 時,可以傳入塊,而 collection 中的每個元素都可能會放在塊里運(yùn)行一變,這種做法通常會大幅簡化編碼過程.
for 循環(huán)
便利數(shù)組的第一種辦法就是采用老式的 for循環(huán),在作為 OC 根基的 C語言 里面,就已經(jīng)有此方法了, 這是個很基本的辦法, 因而功能非常有限.
使用 OC 1.0 的 NSEnumerator 遍歷
NSEnumerator 是個抽象基類,其中只定義了兩個方法,供其具體子類來實現(xiàn)
- (NSArray *)allObject;
- (id) nextObject;
其中關(guān)鍵的方法是 nextObject,它返回枚舉里的下個對象, 每次調(diào)用該方法時,其內(nèi)部數(shù)據(jù)結(jié)構(gòu)都會更新,使得下次調(diào)用方法時能返回下個對象,等到枚舉中的全部對象都已經(jīng)返回之后,在調(diào)用就返回 nil,這個表示達(dá)到枚舉末端了.
Foundation 框架中內(nèi)建的 collection 類都實現(xiàn)了這種遍歷模式,例如:
NSArray* anArray = [...];
NSEnumerator * enumerator = [anArray objectEnumerator];
id object;
while((object = [enumerator nextObject]) != nil){
//...
}
這種寫法的功能與標(biāo)準(zhǔn)的 for 循環(huán)相似,但是代碼卻多了一些,其真正的優(yōu)勢在于.不論遍歷那種 collection 都可以采用這種相似的語法.
快速遍歷
OC 2.0 引入了快速遍歷這一功能, 快速遍歷與使用 NSEnumerator 來遍歷差不多, 語法更為簡潔.for-in 簡化了遍歷collection 所需的語法.
基于 塊 的遍歷方式
在當(dāng)前的 OC 語言中,最新引入的一種做法就是基于 塊 來遍歷. NSArray 中定義了下面這個方法.它可以實現(xiàn)最基本的遍歷功能
- (void)enumerateObjectsUsingBlock:(void(^)(id object, NSUinteger idx, BOOL * stop))block
這個 塊 有三個參數(shù),分別是當(dāng)前迭代所針對的對象,所針對的下標(biāo),以及指向布爾值的指針, 前兩個參數(shù)的含義不言而喻, 而通過第三個參數(shù)所提供的機(jī)制,開發(fā)者可以終止遍歷操作.
此方法勝過其他方式的地方在于:遍歷時可以直接從 塊 中獲取更多信息, 在遍歷數(shù)組時,可以知道當(dāng)前所針對的下標(biāo), 遍歷字典可以同時獲取 鍵 和 值,
另外一個好處是, 能夠修改 塊 的方法簽名, 以免進(jìn)行類型轉(zhuǎn)換
總結(jié):
遍歷 collection 有四種方式, 最基本的是 for循環(huán), 其次是 NSEnumerator 遍歷法 及 快速遍歷法,最新.最先進(jìn) 的是 '塊 枚舉法'
塊枚舉法 本身就能通過 GCD 來并發(fā)執(zhí)行遍歷操作, 無需另行編寫代碼, 而采用其他遍歷方式則無法輕易實現(xiàn)這一點(diǎn)
若提前知道待遍歷的 collection 含有何種對象, 則應(yīng)修改 塊簽名, 之處對象的具體類型.