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]; } }
你可以试试:
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];
}