2012-01-12 50 views
36

我有點偶然發現錯誤,你試圖從NSMutableArray中刪除對象,而其他對象被添加到其他地方。爲了簡單起見,我不知道如何解決它。這是我在做什麼:Objective-C NSMutableArray在枚舉時發生了變異?

我有4個計時器調用4個不同的方法,將對象添加到相同的數組。現在,當我按下某個按鈕時,我需要刪除數組中的所有對象(或至少一些)。所以我試着首先使所有4個定時器無效,然後完成我想要的數組,然後啓動定時器。我認爲這會起作用,因爲我不再使用定時器來枚舉整個數組,但看起來不起作用。

此處有任何建議嗎?

+0

這也發生在我身上,但我沒有從我的NSMutableArray中刪除任何東西。但是,我在後臺線程中添加了項目。它只會拋出這個錯誤,也許每50或100一次,增加...這是唯一的線程,曾經接觸整個應用程序中的數組... – Jesse 2014-04-20 05:29:20

回答

103

這與您的計時器無關。因爲(我認爲)你的定時器都和你的修改方法在同一個線程上工作,所以你不需要停止和啓動它們。 iOS不使用計時器回調中斷模型,他們不得不等待輪到他們就像任何其他的事件:)

你可能做這樣的事情

for (id object in myArray) 
    if (someCondition) 
     [myArray removeObject:object]; 

您不能編輯一個可變陣列,同時在你經歷,所以你需要做一個臨時的數組來保存要刪除

// Find the things to remove 
NSMutableArray *toDelete = [NSMutableArray array]; 
for (id object in myArray) 
    if (someCondition) 
     [toDelete addObject:object]; 

// Remove them 
[myArray removeObjectsInArray:toDelete]; 
+0

我認爲最後兩行應該讀取「(id對象在toDelete) [myArray removeObject:object];'「 – 2012-01-12 11:10:41

+0

@TobiasKlüpfel - 你是對的 - 我編輯了我的答案。 – deanWombourne 2012-01-12 11:13:11

+0

只需使用'-removeObjectsInArray:'。另外,如果通過索引訪問,則可以在遍歷它時進行修改。 – 2012-01-12 11:29:21

22

的東西,你可以這樣來做:

for (id object in [myArray copy]) 
    if (someCondition) 
     [myArray removeObject:object]; 

像@deanWombourne說的,「你不能在編輯一個可變數組的時候通過它」,所以我在這裏做的是創建一個你原始數組的autoreleased副本來枚舉這些對象,所以你可以安全地刪除任何你想要的。

更清晰和更少的鍋爐代碼(我想!)。

更新:刪除autorelease調用,因爲這是一箇舊的答案,前ARC。

+0

非常好:)如果你的'myArray'非常大,可能會出現性能問題,你只能刪除幾個項目,但我當然喜歡它的優雅! – deanWombourne 2012-01-12 14:46:00

+0

這裏最優雅,當然'ARC'不需要'autorelease'。 – mojuba 2013-06-28 16:08:07

+0

除了之前提到的性能問題@deanWombourne之外,每次迭代使用'[myArray copy]'可能會減慢程序的運行速度。我強烈建議在for循環之前創建一個'NSArray'實例(例如'NSArray * tempArray = [myArray copy];'),然後使用它。 – pxpgraphics 2014-11-24 19:01:38

0

雖然高於一切都是真的......我想分享我的經驗與

突變而被枚舉

我所做的一切很簡單,但完全錯全:

for (id obj in d.dataDashBoardGraph) { 
    [tmpData addObject:[obj valueForKey:[[dataToShow[i] componentsSeparatedByString:@"_"] objectAtIndex:1]]]; 

    ... 
} 

即使這引起了mutated being enumerated error。爲了擺脫它:

for (id obj in d.dataDashBoardGraph) { 
    NSString *data = [dataToShow[i] copy]; 
    [tmpData addObject:[obj valueForKey:[[data componentsSeparatedByString:@"_"] objectAtIndex:1]]]; 

    ... 
} 

然後它的工作完美。

-1

的NSMutableArray不能突變而被枚舉,你可以調用你行動之前創建一個小的延遲:

for(id key in resultsDictionary) { 
       if ([key isEqual:whichButtonString]) { 
        // [resultsDictionary removeObjectForKey:whichButtonString]; 
        [self performSelector:@selector(removeKeyFromDictionary:) withObject:whichButtonString afterDelay:1.0]; 
       } 
      } 

然後

-(void) removeKeyFromDictionary : (NSString *) incomingString { 
[resultsDictionary removeObjectForKey:incomingString]; 

}

0

你可以試試:

for (id object in [myArray reverseObjectEnumerator]) 
if (someCondition) 
    [myArray removeObject:object]; 

如果刪除索引x =處的對象索引x + 1,x + 2 ....處的對象索引將被更改。 所以當你使用reverseObjectEnumerator時,刪除一些對象之後數組中對象的索引仍然會正確。

希望得到這個幫助。 (接受的答案是一個明確的解決方案。)

相關問題