for in筋夏、經(jīng)典for循環(huán)和EnumerateObjectsUsingBlock

一直以為for循環(huán)和 for in 是一樣的,例如:

    CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
    NSMutableArray * arr = @[@1,@2,@3,@4,@5].mutableCopy;
    for (NSNumber *obj in arr) {
        NSLog(@"%@",obj);
    }
    CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
    NSLog(@"for in cost: %0.3f",end - start);
    
    CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
    for (int i = 0; i < arr.count; i ++) {
        NSLog(@"%@",arr[i]);
    }
    CFAbsoluteTime endTime = CFAbsoluteTimeGetCurrent();
    NSLog(@"for cost: %0.3f",endTime - startTime);
屏幕快照 1.png

但是偶然間寫了這么一段就崩潰了

    for (NSString * obj in arr) {
        if ([obj integerValue] == 2) {
            [arr addObject:@"6"];
        }
    }
    CFAbsoluteTime end = CFAbsoluteTimeGetCurrent();
    NSLog(@"for in cost: %0.3f Arr:%@",end - start,arr);
2FB1AD54-CC19-4FC0-BEF0-30B718922D60.png

但是如果寫成for循環(huán)就沒有問題,然后就去百度了一下發(fā)現(xiàn):如果在for in 循環(huán)里,對這個(gè)數(shù)組進(jìn)行了修改的話,無論是增挤土,刪,修改數(shù)組元素位置误算,都會扔一個(gè)異常出來仰美,枚舉的過程中數(shù)組發(fā)生了突變(<__NSArrayM: 0xa4fc000> was mutated while being enumerated.)

for in實(shí)際上是快速枚舉,跟for循環(huán)意義上還是有區(qū)別的儿礼。NSArray的枚舉操作中有一條需要注意:對于可變數(shù)組進(jìn)行枚舉操作時(shí)筒占,不能通過添加或刪除對象等這類操作來改變數(shù)組容器,否則就會報(bào)錯(cuò).而本身這種操作也是有問題的,數(shù)組容器已經(jīng)改變蜘犁,可能遍歷到?jīng)]有分配的位置翰苫,用for循環(huán)機(jī)器不能自己察覺,但是枚舉器可以察覺这橙。

enumerateKeysAndObjectsUsingBlock用法

    NSDictionary * dic = [NSDictionary dictionaryWithObjectsAndKeys:@"obj1",@"key1",@"obj2",@"key2", nil];
    [dic enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
        NSLog(@"value for key %@ is %@ ", key, value);
        if ([@"key2" isEqualToString:key]) {
            *stop = YES;
        }
    }];

NSDictionary有一個(gè)方法叫enumerateKeysAndObjectsUsingBlock奏窑,它就一個(gè)參數(shù)就是block,這個(gè)block攜帶了三個(gè)參數(shù)屈扎,這將要把dictionary里面的key和value每次一組傳遞到block埃唯,enumerateKeysAndObjectsUsingBlock會遍歷dictionary并把里面所有的key和value一組一組的展示給你,每組都會執(zhí)行這個(gè)block鹰晨。這其實(shí)就是傳遞一個(gè)block到另一個(gè)方法墨叛,在這個(gè)例子里它會帶著特定參數(shù)被反復(fù)調(diào)用止毕,直到找到一個(gè)key2的key,然后就會通過重新賦值那個(gè)BOOL *stop來停止運(yùn)行漠趁,停止遍歷同時(shí)停止調(diào)用block扁凛。

更詳細(xì)的用法
(http://blog.itpub.net/12231606/viewspace-1084119/)

enumerateObjectsWithOptions使用

NSArray *array = [[NSArray alloc]initWithObjects:@"a",@"b",@"c",@"d",@"e",@"f", nil];
    
    //遍歷數(shù)組元素
    [array enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"obj=%@   idx=%ld",obj,idx);
    }];
    
    //如果指定了NSEnumerationConcurrent順序,那么底層通過GCD來處理并發(fā)執(zhí)行事宜闯传,具體實(shí)現(xiàn)可能會用到dispatch group谨朝。也就是說,這個(gè)會用多線程來并發(fā)實(shí)現(xiàn)甥绿,并不保證按照順序執(zhí)行
    
    //NSEnumerationReverse 倒序排列
    [array enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"idx=%ld, id=%@", idx, obj);
        
        //當(dāng)需要結(jié)束循環(huán)的時(shí)候,調(diào)用stop,賦予YES
        if (idx ==3) {
            *stop = YES;
        }
        
    }];
    //NSIndexSet類代表一個(gè)不可變的獨(dú)特的無符號整數(shù)的集合,稱為索引,因?yàn)槭褂盟鼈兊姆绞阶直摇_@個(gè)集合被稱為索引集    唯一的,有序的共缕,無符號整數(shù)的集合
    [NSIndexSet indexSetWithIndex:1];//創(chuàng)建一個(gè)索引集合洗出,根據(jù)索引值
    [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0,8)];//創(chuàng)建一個(gè)索引集合,根據(jù)一個(gè)NSRange對象

    [array enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0,3)] options:NSEnumerationReverse usingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSLog(@"\n\n\nidx=%ld, id=%@", idx, obj);
    }];

for in图谷、經(jīng)典for循環(huán)和EnumerateObjectsUsingBlock 的比較

  1. 對于集合中對象數(shù)很多的情況下共苛,for in 的遍歷速度非常之快,但小規(guī)模的遍歷并不明顯(還沒普通for循環(huán)快)
  2. Value查詢index的時(shí)候, 面對大量的數(shù)組推薦使用 enumerateObjectsWithOptions的并行方法.
  3. 遍歷字典類型的時(shí)候, 推薦使用enumerateKeysAndObjectsUsingBlock,block版本的字典遍歷可以同時(shí)取key和value(forin只能取key再手動(dòng)取value)

參考文章:
(http://www.reibang.com/p/ef3f1731a353)
(http://blog.sunnyxx.com/2014/04/30/ios_iterator/)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蜓萄,一起剝皮案震驚了整個(gè)濱河市隅茎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌嫉沽,老刑警劉巖辟犀,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異绸硕,居然都是意外死亡堂竟,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進(jìn)店門玻佩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來出嘹,“玉大人,你說我怎么就攤上這事咬崔∷凹冢” “怎么了?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵垮斯,是天一觀的道長郎仆。 經(jīng)常有香客問我,道長兜蠕,這世上最難降的妖魔是什么扰肌? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮熊杨,結(jié)果婚禮上曙旭,老公的妹妹穿的比我還像新娘盗舰。我一直安慰自己,他們只是感情好桂躏,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布钻趋。 她就那樣靜靜地躺著,像睡著了一般沼头。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上书劝,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天进倍,我揣著相機(jī)與錄音,去河邊找鬼购对。 笑死猾昆,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的骡苞。 我是一名探鬼主播垂蜗,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼解幽!你這毒婦竟也來了贴见?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤躲株,失蹤者是張志新(化名)和其女友劉穎片部,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霜定,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡档悠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了望浩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辖所。...
    茶點(diǎn)故事閱讀 40,561評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖磨德,靈堂內(nèi)的尸體忽然破棺而出缘回,到底是詐尸還是另有隱情,我是刑警寧澤典挑,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布切诀,位于F島的核電站,受9級特大地震影響搔弄,放射性物質(zhì)發(fā)生泄漏幅虑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一顾犹、第九天 我趴在偏房一處隱蔽的房頂上張望倒庵。 院中可真熱鬧褒墨,春花似錦、人聲如沸擎宝。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绍申。三九已至噩咪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間极阅,已是汗流浹背胃碾。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留筋搏,地道東北人仆百。 一個(gè)月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像奔脐,于是被迫代替她去往敵國和親俄周。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內(nèi)容