何爲迭代器模式?算法
迭代器提供了一種順序訪問集合對象中元素的方法,而無需暴漏結構的底層表示和細節。遍歷集合中元素的職能從集合自己轉移到迭代器對象。迭代器定義了一個用於訪問集合元素並記錄當前元素的接口。不一樣的迭代器能夠執行不一樣的策略。數組
什麼時候使用迭代器模式?框架
@:須要訪問組合對象的內容,而又不暴漏其內部表示。spa
@:須要經過多種方式遍歷組合對象。指針
@:須要提供一個統一的接口,用來遍歷各類類型的組合對象。code
在Cocoa Touch框架中使用迭代器模式?orm
基礎框架中的NSEnumerator類實現了迭代器模式。抽象NSEnumerator類的私有具體子類返回枚舉器對象,可以順序遍歷各類集合——數組、集合、字典,把集合中的對象返回給客戶端。對象
NSDirectoryEnumerator,這個類的實例遞歸枚舉文件系統中一個目錄的內容。NSArray、NSSet、NSDictionary這樣的集合類,定義了返回與集合類型相應的NSEnumerator子類實例的方法。全部的枚舉器都以一樣的方式工做,能夠在一個循環中向枚舉器發送nextObject消息,從枚舉器取得對象,直到它返回nil表示遍歷結束。遞歸
1.NSEnumerator索引
咱們可使用NSEnumerator來枚舉NSArray、NSDictionary和NSSet對象中的元素。NSEnumerator自己是個抽象類,它有依靠幾個工廠方法,如objectEnumrator或keyEnumerator,來建立並返回相應的具體枚舉器對象。代碼以下:
NSArray *array = @[@"張三", @"李四", @"王五"]; NSEnumerator *itemEnumerator = [array objectEnumerator]; NSString *item; while (item = [itemEnumerator nextObject]) { NSLog(@"item is :%@", item); }
2015-08-28 16:48:05.463 NSEnumatroDemo[55301:3712762] item is :張三 2015-08-28 16:48:05.463 NSEnumatroDemo[55301:3712762] item is :李四 2015-08-28 16:48:05.464 NSEnumatroDemo[55301:3712762] item is :王五
使用NSEnumerator對數組進行遍歷,當消息調用[itemEnumerator nextObject]會返回nil,而後枚舉過程就結束了。
2.基於塊的枚舉
從iOS4.0後,在NSArray、NSDictionary和NSSet對象中引入了新方法,用於基於塊的枚舉。其中一個方法叫enumerateObjectsUsingBlock:(void(^)(id obj, NSUInteger idx, BOOL *stop))block。咱們能夠把本身的算法定義在內嵌到消息調用之中的塊裏,或者在別的什麼地方預約義一個塊,而後做爲參數傳給消息調用。以下代碼:
NSArray *array = @[@"張三", @"李四", @"王五"]; NSString *str = @"李四"; [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { NSLog(@"item is :%@", obj); if ([obj localizedStandardCompare:str] == NSOrderedSame) { *stop = YES; NSLog(@"中止遍歷"); } }];
2015-08-28 17:10:03.556 NSEnumatroDemo[55478:3723216] item is :張三 2015-08-28 17:10:03.557 NSEnumatroDemo[55478:3723216] item is :李四 2015-08-28 17:10:03.557 NSEnumatroDemo[55478:3723216] 中止遍歷
若是array數組中有字符串"李四",那麼久把指針*stop設置爲YES,以通知array對象提早中止遍歷。
NSSet對象中基於塊的枚舉與NSArray中的很是相似,只是在塊的參數中沒有idx參數。由於集合中的元素是無序的。
使用NSArray、NSDictionary和NSSet的內部迭代器的一個重要好處是,處理其內容的算法能夠在其餘地方由其餘開發人員來定義。與傳統的for循環中定義的算法不一樣,定義清晰的塊能夠被複用。當塊逐漸變大時,可把它們放到單獨的實現文件中,不跟其餘代碼擠在一塊兒。
3.快速枚舉
從iOS2.0後提供了一種枚舉,快速枚舉,也是蘋果推薦的枚舉方法。它容許把集合對象的枚舉直接用做for循環的一部分,無需使用其餘枚舉對象,並且比傳統的機遇索引的for循環效率更高。如今枚舉循環使用指針運算,讓它比使用NSEnumerator的標準方法效率更高。
要使用快速枚舉,集合類須要實現NSFastEnumeration協議,以向運行庫提供關於集合的必要信息。基礎框架中的全部集合類與NSEnumerator類都支持快速枚舉。所以沒必要使用while循環從NSEnumerator枚舉每一個元素,直到nextObject返回nil。代碼以下:
NSArray *array = @[@"張三", @"李四", @"王五"]; for (id item in array) { NSLog(@"item is :%@", item); }
2015-08-28 17:28:18.619 NSEnumatroDemo[55596:3730966] item is :張三 2015-08-28 17:28:18.620 NSEnumatroDemo[55596:3730966] item is :李四 2015-08-28 17:28:18.620 NSEnumatroDemo[55596:3730966] item is :王五
4.內部枚舉
NSArray有個實例方法叫(void)makeObjectsPerformSelector:(SEL)aSelector,它容許客戶端向數組中每一個元素髮送一個消息,讓每一個元素執行指定的aSelector。能夠用前面提到的任何一種枚舉方法讓每一個元素執行相同的選擇器,達到相同的目的。這個方法在內部枚舉集合並向每一個元素髮送performSelector:消息。這種方式的缺點是若是集合中任何元素不響應選擇器,就會拋出異常。所以它主要使用於不須要太多運行時檢查的簡單操做。
這就是迭代器模式。