iOS中遍歷的方法總結(jié)
在iOS開(kāi)發(fā)中,可以使用多種方法進(jìn)行元素遍歷,具體有一下幾種:
經(jīng)典for循環(huán)
NSArray *iosArray = @[@"a", @"b", @"c", @"d", @"e", @"f", @"g"]; for (int i = 0; i < iosArray.count; i++) { //處理數(shù)組中數(shù)據(jù) NSLog(@"%@", iosArray[i]); }
NSEnumerator遍歷
NSArray *iosArray = @[@"a", @"b", @"c", @"d", @"e", @"f", @"g"]; NSEnumerator *enumerator = [iosArray objectEnumerator];//正向遍歷 // NSEnumerator *enumerator = [iosArray reverseObjectEnumerator];//反向遍歷 id object; while ((object = [enumerator nextObject]) != nil) { //處理枚舉器中的數(shù)據(jù) NSLog(@"%@", object); }
for-in快速遍歷
NSArray *iosArray = @[@"a", @"b", @"c", @"d", @"e", @"f", @"g"]; for (NSString *obj in iosArray) { //處理數(shù)組中的數(shù)據(jù) NSLog(@"%@", obj); }
EnumeratorBlock遍歷
NSArray *iosArray = @[@"a", @"b", @"c", @"d", @"e", @"f", @"g"]; [iosArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { NSLog(@"%@", obj); if ([obj isEqualToString:@"e"]) { *stop = YES; // 跳出遍歷 } }];
另外,EnumeratorBlock還支持反向遍歷,并發(fā)遍歷,并發(fā)遍歷可以使用多核的優(yōu)化,充分利用系統(tǒng)的資源。
反向遍歷
NSArray *iosArray = @[@"a", @"b", @"c", @"d", @"e", @"f", @"g"]; [iosArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSString *obj, NSUInteger idx, BOOL * _Nonnull stop) { NSLog(@"%@", obj); if ([obj isEqualToString:@"e"]) { *stop = YES; } }];
并發(fā)遍歷
NSArray *iosArray = @[@"a", @"b", @"c", @"d", @"e", @"f", @"g"]; 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; } }];
dispatch_apply遍歷
dispatch_apply類似于for循環(huán),這里需要注意的是,dispatch_apple是同步調(diào)用,調(diào)用完畢返回結(jié)果,并且由于是GCD實(shí)現(xiàn),所以可以使用并發(fā)隊(duì)列或者是串行隊(duì)列。代碼如下:
dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_CONCURRENT); // dispatch_queue_t queue = dispatch_queue_create("queue", DISPATCH_QUEUE_SERIAL); // 串行隊(duì)列 dispatch_apply(array.count, queue, ^(size_t i) { Enumerate *enumerate = [array objectAtIndex:i]; NSLog(@"number: %ld", enumerate.number); });
遍歷的注意事項(xiàng)
for循環(huán)中不要修改數(shù)組
遍歷過(guò)程中是不能隨便刪除遍歷的元素的,如果需要?jiǎng)h除元素,可以先復(fù)制一份出來(lái),比如如下的代碼會(huì)有問(wèn)題:
NSMutableArray *iosArray = @[@"a", @"b", @"c", @"d", @"e", @"f", @"g"]; for (NSString *obj in iosArray) { //處理數(shù)組中的數(shù)據(jù) if([@"e" isEqualTo:obj]) { [iosArray removeObject:obj]; } }
但是使用enumerateBlock可以在block內(nèi)部做removeObject操作,原因應(yīng)該是和Block的特性有關(guān), 在Block中會(huì)保存變量的值,而不會(huì)隨變量的值的改變而改變 。
遍歷的速率
當(dāng)數(shù)組容量很大的時(shí)候,如果只是進(jìn)行數(shù)組遍歷的話,使用for-in是最快速的,其次是并發(fā)遍歷,這個(gè)很多人都以為enumerateBlock是最快的。
遍歷實(shí)踐tips
數(shù)組分組
在開(kāi)發(fā)中,有時(shí)需要對(duì)數(shù)組進(jìn)行某種情況的分組,比如,一個(gè)擁有很多消息模型的數(shù)組,我們需要根據(jù)消息的創(chuàng)建月份進(jìn)行分組,那么可以使用下面的方法實(shí)現(xiàn):
NSMutableSet *set=[NSMutableSet set]; NSArray *array = @[message1, message2, message3, message4, message5, message6, message7]; __block NSArray *tempDataArray = [NSArray arrayWithArray:array]; [tempDataArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { [set addObject:obj.month];//利用set不重復(fù)的特性,得到有多少組,根據(jù)數(shù)組中消息的月份屬性 }]; [set enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {//遍歷set數(shù)組 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.month = %@", obj];//創(chuàng)建謂詞篩選器 NSArray *group = [tempDataArray filteredArrayUsingPredicate:predicate];//用數(shù)組的過(guò)濾方法得到新的數(shù)組,在添加的最終的數(shù)組 }
倒序遍歷
倒序遍歷也很常見(jiàn),可以使用上面的反向遍歷來(lái)實(shí)現(xiàn)。
set排序
這個(gè)和Emunerate其實(shí)沒(méi)有關(guān)系,但是也很實(shí)用,我們知道set是無(wú)序的,但是有時(shí)需要實(shí)現(xiàn)有順序的set,可以使用下面來(lái)實(shí)現(xiàn):
//由于set無(wú)序,現(xiàn)將set轉(zhuǎn)換成nsarray NSArray *sortDescriptor = @[[[NSSortDescriptor alloc] initWithKey:@"self" ascending:NO]]; NSArray *sortSetArray = [set sortedArrayUsingDescriptors:sortDescriptor];
其實(shí)原理是將set轉(zhuǎn)化成array來(lái)實(shí)現(xiàn)的。
總結(jié)
遍歷在我們?nèi)粘i_(kāi)發(fā)中十分常見(jiàn),根據(jù)應(yīng)用場(chǎng)景,選擇合適的遍歷方法才是我們需要關(guān)系的。這篇文章總結(jié)了下遍歷的種類和注意事項(xiàng),希望能幫助到有需要的同學(xué)。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
基于UIControl控件實(shí)現(xiàn)ios點(diǎn)贊功能
在開(kāi)發(fā)當(dāng)中,可能很多時(shí)候都需要做個(gè)點(diǎn)贊的需求,如果用按鈕實(shí)現(xiàn),按鈕作為一個(gè)系統(tǒng)復(fù)合控件,外部是一個(gè) View--》UIControl的容器,本文給大家分享一個(gè)基于UIControl控件實(shí)現(xiàn)ios點(diǎn)贊功能,需要的朋友可以參考下2015-09-09iOS開(kāi)發(fā)之手勢(shì)gesture詳解
本篇文章介紹了iOS開(kāi)發(fā)之手勢(shì)gesture,現(xiàn)在分享給大家,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2016-11-11詳細(xì)整理iOS中UITableView的性能優(yōu)化
最近在微博上看到一個(gè)很好的開(kāi)源項(xiàng)目,是關(guān)于如何優(yōu)化UITableView的,加上正好最近也在優(yōu)化項(xiàng)目中的類似朋友圈功能這塊,思考了很多關(guān)于UITableView的優(yōu)化技巧,所以決定詳細(xì)的整理下對(duì)優(yōu)化UITableView的理解,需要的朋友們可以參考借鑒。2017-03-03一個(gè)iOS上的秒表小應(yīng)用的實(shí)現(xiàn)方法分享
這篇文章主要介紹了一個(gè)iOS上的秒表小應(yīng)用的實(shí)現(xiàn)方法分享,代碼基于傳統(tǒng)的Objective-C,需要的朋友可以參考下2015-10-10iOS UIAlertController中UITextField添加晃動(dòng)效果與邊框顏色詳解
這篇文章主要給大家介紹了關(guān)于iOS UIAlertController中UITextField添加晃動(dòng)效果與邊框顏色的相關(guān)資料,實(shí)現(xiàn)后的效果非常適合在開(kāi)發(fā)中使用,文中給出了詳細(xì)的示例代碼,需要的朋友可以參考借鑒,下面隨著小編來(lái)一起看看吧。2017-10-10IOS 聊天界面(自適應(yīng)文字)的實(shí)現(xiàn)
本文主要介紹一個(gè)實(shí)現(xiàn)聊天界面的思路過(guò)程,具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-03-03iOS安全防護(hù)系列之字符串及系統(tǒng)函數(shù)隱藏詳解
這篇文章主要給大家介紹了關(guān)于iOS安全防護(hù)系列之字符串及系統(tǒng)函數(shù)隱藏的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-07-07iOS中UIScrollerView的用法及基于AotoLayout的控件懸停
這篇文章主要介紹了iOS中UIScrollerView的用法及基于AotoLayout的控件懸停,文中對(duì)于UIScrollerView的方法及屬性介紹地非常詳細(xì),十分推薦,示例代碼為Objective-C,需要的朋友可以參考下2016-03-03