第一種方式:for循環(huán)
-
遍歷數(shù)組
NSArray *iosArray = @[@"L", @"O", @"V", @"E", @"I", @"O", @"S"]; for (int i = 0; i < iosArray.count; i++) { //處理數(shù)組中數(shù)據(jù) NSLog(@"%@", iosArray[i]); }
-
遍歷字典
NSDictionary *dict = @{@"1":@"11", @"2":@"22", @"3":@"33"}; NSArray *keysArray = [dict allKeys]; for (int i = 0; i < keysArray.count; i++) { //根據(jù)鍵值處理字典中的每一項(xiàng) NSString *key = keysArray[i]; NSString *value = dict[key]; NSLog(@"%@", value); }
- 因?yàn)樽值浜蛃et是無序的贾费,所以我們無法根據(jù)特定的整數(shù)下標(biāo)來直接訪問其中的值钦购,于是需要先獲取字典中的鍵或者set的所有對(duì)象,這樣就可以在有序數(shù)組上進(jìn)行遍歷了褂萧。然而創(chuàng)建出多一個(gè)數(shù)組押桃,會(huì)保留collection中的所有對(duì)象,占用了內(nèi)存
-
優(yōu)缺點(diǎn):
優(yōu)點(diǎn):被廣泛使用导犹,容易接受唱凯,操作簡(jiǎn)單
缺點(diǎn):遍歷字典和set比較繁瑣,會(huì)占用比較多的系統(tǒng)資源
第二種方式:快速遍歷
-
遍歷數(shù)組
NSArray *iosArray = @[@"L", @"O", @"V", @"E", @"I", @"O", @"S"]; for (NSString*obj in iosArray) { //處理數(shù)組中的數(shù)據(jù) if ([obj isEqualToString:@"E"]) { NSLog(@"%@",obj); } }
執(zhí)行結(jié)果
2016-09-02 11:35:38.553 bianli_demo[1914:78780] E
-
遍歷字典
NSDictionary *dict = @{@"1":@"11", @"2":@"22", @"3":@"33"};
for (NSString *key in dict) {
if ([key isEqualToString:@"2"]) {
NSLog(@"%@",dict[key]);
}
}
```
執(zhí)行結(jié)果
```
2016-09-02 11:35:38.553 bianli_demo[1914:78780] 22
```
- 反向遍歷可以使用for(NSString *obj in [iosArray reverseObjectEnumerator])
- 總結(jié):
- 優(yōu)點(diǎn):語(yǔ)法簡(jiǎn)潔谎痢,使用方便磕昼,效率高;
- 缺點(diǎn):
- 1.無法方便獲取當(dāng)前遍歷的下標(biāo)
- 2.無法再遍歷過程中修改被遍歷的collection节猿,否則會(huì)導(dǎo)致崩潰
第三種方式:NSEnumerator
-
NSEnumerator是一個(gè)抽象基類票从,其中定義了2個(gè)方法,使其子類實(shí)現(xiàn):
(nullable ObjectType)nextObject;
@property(readonly,copy)NSArray*allObjects;
其中nextObject是關(guān)鍵方法滨嘱,它返回枚舉里的下一個(gè)對(duì)象峰鄙,每次調(diào)用改方法,內(nèi)部結(jié)構(gòu)都會(huì)更新太雨,使得下一次調(diào)用方法時(shí)能返回下一個(gè)對(duì)象吟榴,等到枚舉中全部的對(duì)象都已經(jīng)返回之后,再調(diào)用就會(huì)返回nil囊扳,表示達(dá)到了枚舉的末端吩翻。
-
遍歷數(shù)組
NSEnumerator *enumerator = [_iosArray objectEnumerator];//正向遍歷 id object ; while ((object = [enumerator nextObject])!= nil) { //處理枚舉器中的數(shù)據(jù) NSLog(@"object = %@",object); }
執(zhí)行結(jié)果
2016-09-02 12:03:25.043 get&post-test[2146:91583] object = L 2016-09-02 12:03:25.044 get&post-test[2146:91583] object = O 2016-09-02 12:03:25.044 get&post-test[2146:91583] object = V 2016-09-02 12:03:25.044 get&post-test[2146:91583] object = E 2016-09-02 12:03:25.044 get&post-test[2146:91583] object = I 2016-09-02 12:03:25.044 get&post-test[2146:91583] object = O 2016-09-02 12:03:25.044 get&post-test[2146:91583] object = S
-
遍歷字典
NSEnumerator *enumerator2 = _dict.keyEnumerator; id obj2 ; while ((obj2= [enumerator2 nextObject]) != nil) { NSLog(@"obj2_keyValue = %@",_dict[obj2]); }
執(zhí)行結(jié)果
2016-09-02 12:03:25.044 get&post-test[2146:91583] obj2_keyValue = 11
2016-09-02 12:03:25.045 get&post-test[2146:91583] obj2_keyValue = 22
2016-09-02 12:03:25.045 get&post-test[2146:91583] obj2_keyValue = 33
```
- 總結(jié)
- 優(yōu)點(diǎn):代碼容易讀兜看,不需要定義額外的數(shù)組
- 缺點(diǎn):
1.無法直接獲取遍歷操作的下表,需要另外聲明變量記錄
2.需要自行創(chuàng)建NSEnumerator對(duì)象狭瞎。
第四種:基于塊的遍歷方式
蘋果封裝的高效细移、優(yōu)雅、易用的一套接口熊锭,筆者極力推薦的使用方法
-
遍歷數(shù)組
self.iosArray = @[@"L", @"O", @"V", @"E", @"I", @"O", @"S"]; /** * 遍歷數(shù)組 * * @param obj 表示數(shù)組中元素 * @param idx 表示元素的下標(biāo) * @param stop 控制遍歷何時(shí)停止葫哗,使用要在前面加* * * @return */ [_iosArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { NSLog(@"%@",obj); if ([obj isEqualToString:@"O"]) { *stop = YES; } }];
執(zhí)行結(jié)果
2016-09-02 14:47:28.441 get&post-test[2282:121901] L 2016-09-02 14:47:28.441 get&post-test[2282:121901] O
-
遍歷字典
NSDictionary *dict = @{@"1":@"11", @"2":@"22", @"3":@"33"}; /** * 遍歷字典 * * @param key 字典key值 * @param obj 字典value值 * @param stop 控制遍歷何時(shí)停止 * * @return */ [_dict enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { NSLog(@"key = %@",key); NSLog(@"value = %@",obj); if ([key isEqualToString:@"2"]) { *stop = YES; } }];
執(zhí)行結(jié)果
2016-09-02 14:54:38.816 get&post-test[2349:125565] value = 11 2016-09-02 14:54:38.816 get&post-test[2349:125565] key = 2 2016-09-02 14:54:38.816 get&post-test[2349:125565] value = 22
-
注意
:-
若已知collection里對(duì)象的數(shù)據(jù)類型,可以修改塊簽名球涛。知道對(duì)象的精確類型后劣针,編譯器就可以檢測(cè)開發(fā)者是否調(diào)用了該對(duì)象所不具有的方法,并在發(fā)現(xiàn)問題是報(bào)錯(cuò)亿扁。
NSDictionary *dict = @{@"1":@"11", @"2":@"22", @"3":@"33"}; //此處直接將key和value的類型改為nsstring [dict enumerateKeysAndObjectsUsingBlock:^(NSString key, NSString obj, BOOL * _Nonnull stop) { NSLog(@"%@", obj); if ([obj isEqualToString:@"22"]) { *stop = YES; } }];
-
-
反向遍歷
//反向遍歷數(shù)組 [_iosArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { NSLog(@"%@",obj); if (obj == nil) { *stop = YES; } }]; //反向遍歷字典 [_dict enumerateKeysAndObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSString* key, NSString* obj, BOOL * _Nonnull stop) { NSLog(@"key = %@, value = %@",key,obj); if (key == nil) { *stop = YES; } }];
執(zhí)行結(jié)果
2016-09-02 15:14:49.776 get&post-test[2527:135482] S 2016-09-02 15:14:49.777 get&post-test[2527:135482] O 2016-09-02 15:14:49.777 get&post-test[2527:135482] I 2016-09-02 15:14:49.777 get&post-test[2527:135482] E 2016-09-02 15:14:49.777 get&post-test[2527:135482] V 2016-09-02 15:14:49.777 get&post-test[2527:135482] O 2016-09-02 15:14:49.777 get&post-test[2527:135482] L 2016-09-02 15:14:49.778 get&post-test[2527:135482] key = 1, value = 11 2016-09-02 15:14:49.778 get&post-test[2527:135482] key = 2, value = 22 2016-09-02 15:14:49.778 get&post-test[2527:135482] key = 3, value = 33
-
并發(fā)遍歷
-
并發(fā)遍歷:
NSEnumerationConcurrent
;也就是可以同時(shí)遍歷collection的幾個(gè)元素捺典,具體數(shù)量根據(jù)系統(tǒng)資源而定,這樣會(huì)充分利用系統(tǒng)資源从祝,高效快捷的完成collection的遍歷襟己,系統(tǒng)底層會(huì)通過gcd來處理并發(fā)事宜,開發(fā)者不需擔(dān)心內(nèi)存和線程牍陌,其他方式若要實(shí)現(xiàn)高效的并發(fā)遍歷十分有難度擎浴,通過塊枚舉遍歷,改變collection不會(huì)引期代碼崩潰
NSArray *iosArray = @[@"L", @"O", @"V", @"E", @"I", @"O", @"S"]; NSMutableArray *iosMutableArray = [NSMutableArray arrayWithArray:iosArray]; [iosMutableArray enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(NSString *obj, NSUInteger idx, BOOL * _Nonnull stop) { obj = [NSString stringWithFormat:@"_%@", obj]; [iosMutableArray replaceObjectAtIndex:idx withObject:obj]; NSLog(@"%@", obj); if ([obj isEqualToString:@"_I"]) { *stop = YES; } }];
執(zhí)行結(jié)果
2016-09-02 15:27:06.123 get&post-test[2599:140840] _V 2016-09-02 15:27:06.123 get&post-test[2599:140708] _L 2016-09-02 15:27:06.124 get&post-test[2599:140708] _I 2016-09-02 15:27:06.123 get&post-test[2599:140837] _E 2016-09-02 15:27:06.124 get&post-test[2599:140708] _S 2016-09-02 15:27:06.123 get&post-test[2599:140838] _O 2016-09-02 15:27:06.124 get&post-test[2599:140840] _O
-
-
總結(jié)
- 優(yōu)點(diǎn)
- 1.可以完美實(shí)現(xiàn)for循環(huán)的所有功能毒涧。
- 2.可以方便獲取集合中的每一項(xiàng)元素贮预。
- 3.可以修改塊簽名
- 4.可以實(shí)現(xiàn)并發(fā)循環(huán)功能,系統(tǒng)底層會(huì)通過gcd處理并發(fā)事宜
- 5.效率高契讲,能夠提升程序性能仿吞,開發(fā)者可以專注于業(yè)務(wù)邏輯,而不必?fù)?dān)心線程和內(nèi)存問題
- 6.提供了循環(huán)遍歷的參數(shù)捡偏,NSEnumerationReverse用來實(shí)現(xiàn)倒序循環(huán)唤冈。NSEnumerationConcurrent用來實(shí)現(xiàn)并發(fā)遍歷,兩個(gè)參數(shù)可以同時(shí)使用银伟;
- 缺點(diǎn)
- 1.這里使用了block你虹,需要注意在block里容易引起的保留環(huán)問題,比如使用self調(diào)用方法時(shí)彤避,把self轉(zhuǎn)化成弱引用即可打破保留環(huán)傅物。如__weak __typeof(self)weakSelf = self 或者 __weak MyController *weakSelf = self; 在block里使用weakSelf即可。
- 優(yōu)點(diǎn)
-
注意
:使用基于塊的遍歷時(shí)是可以修改遍歷的元素的忠藤,不會(huì)導(dǎo)致崩潰挟伙,但是如果 要?jiǎng)h除遍歷的元素會(huì)導(dǎo)致后面的元素?zé)o法遍歷而崩潰楼雹,解決辦法有2種 1模孩、一種是復(fù)制一份原集合的副本尖阔,對(duì)副本進(jìn)行操作,找出所要操作的元素后再處理原集合 2榨咐、使用反向遍歷介却,反向遍歷刪除元素后不會(huì)導(dǎo)致崩潰。