Objective-C的NSMutableArray枚举时突变?

我有点偶然发现错误,你试图从NSMutableArray中删除对象,而其他对象被添加到其他地方。 为了简单起见,我不知道如何解决这个问题。 这是我在做什么:

我有4个计时器调用4个不同的方法,将对象添加到相同的数组。 现在,当我按下某个button,我需要删除数组中的所有对象(或至less一些)。 所以我试着先把所有的4个定时器全部无效,然后用数组来做我想要的工作,然后启动定时器。 我以为这会工作,因为我不再使用定时器枚举整个数组,但看起来不起作用。

这里有什么build议?

这与你的计时器无关。 因为(我认为)你的计时器都和你的修改方法在同一个线程上工作,所以你不需要停止和启动它们。 iOS不使用定时器callback的中断模式,它们必须像其他事件一样等待。

你可能正在做类似的事情

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

你不能编辑一个可变数组,所以你需要创build一个临时数组来存放你想要移除的东西

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

你可以这样做:

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

像@deanWombourne说的,“你不能在编辑一个可变数组的时候”,所以我在这里做的是创build一个原始数组的autoreleased副本来枚举这些对象,所以你可以安全的删除任何你想要的。

更清晰和更less的锅炉代码(我想!)。

更新 :删除autorelease电话,因为这是一个旧的答案,前ARC。

您可以使用@synchronized()指令来locking数组,同时对其进行变更:

 if (someCondition) { @synchronized(yourArray) { [yourArray removeObject:someObject]; } } 

更多信息在http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocThreading.html

你可以试试:

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

如果在索引x =>删除对象索引x + 1,x + 2 ….处的对象的索引将被更改。 所以当你使用reverseObjectEnumerator的时候 ,删除一些对象之后数组中对象的索引仍然是正确的。

希望这个帮助。 (接受的答案是一个明确的解决scheme。)

虽然首先是真实的…我会分享我的经验

枚举时变异

我所做的是简单但完全错误的:

 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]]]; ... } 

然后它完美的工作。

在枚举时,NSMutableArray不能被改变,你可以在调用你的动作之前创build一个小的延迟:

  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]; 

}