Objective-C 2.0和Fast Enumeration抛出异常

时间:2009-02-16 20:22:33

标签: objective-c cocoa cocoa-touch enumeration

我有一段代码,类似于以下内容:

for (NSDictionary *tmp in aCollection) {
   if ([[bar valueForKey:@"id"] isEqualToString:[tmp valueForKey:@"id"]])
   {
      break;
   }
   else
   {
      [aCollection addObject:bar];
       }
 }

这在Objective-C 2.0中是否属于技术上的例外?看起来你不能用快速枚举变异集合。这是错误的结果:

*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <NSCFArray: 0x396000> was mutated while being enumerated.'

解决这个问题的最佳方法是什么?

7 个答案:

答案 0 :(得分:12)

解决问题的方法不是在枚举时改变数组(例如添加对象):)

这里的问题是通过添加/删除元素来修改数组可能会导致枚举值变为无效,因此它会成为问题。

在您的情况下解决此问题的最简单方法是修复代码中的错误。你的代码正在为数组中的每个项目执行“else add”子句,我很确定这不是你想要的。

试试这个;

bool found = false;
for (NSDictionary *tmp in aCollection)
{
   if ([[bar valueForKey:@"id"] isEqualToString:[tmp valueForKey:@"id"]])
   {
      found = true;
      break;
   }
}

if (!found)
{
 [aCollection addObject:bar];
}

答案 1 :(得分:6)

制作该集合的副本并进行迭代。然后,您可以毫无问题地换出或添加到原始集合。

答案 2 :(得分:6)

该行

[aCollection addObject:bar]

是你的问题。枚举时不能修改aCollection。更好的方法是创建一个临时NSMutableArray,向其中添加bar,然后使用临时数组调用[aCollection addObjectsFromArray:]

例如:

NSMutableArray *foundObjects = [NSMutableArray array];
for (NSDictionary *aDictionary in aCollection) {
    if ([[bar objectForKey:@"id"] isEqual:[aDictionary objectForKey:@"id"]])
       break;

    [foundObjects addObject:bar];
}
[aCollection addObjectsFromArray:foundObjects];

答案 3 :(得分:3)

The Objective-C 2.0 Programming Language,您无法修改枚举的集合:

  

枚举是“安全的” - 枚举器具有变异防护,因此如果您在枚举期间尝试修改集合,则会引发异常。

答案 4 :(得分:2)

只需复制数组即可。否则你会搞乱你正在迭代的集合:

for (NSDictionary *tmp in aCollection.copy) {
  if ([[bar valueForKey:@"id"] isEqualToString:[tmp valueForKey:@"id"]])
     break;
  [aCollection addObject:bar];
}

答案 5 :(得分:1)

其他人都提供了有用的答案,所有这些答案都是正确的。

然而,您的代码并没有按照他们的想法行事。它可能不会做你认为它做的事情。

如果枚举器返回的第一个对象与bar不匹配,则尝试将“bar”添加到集合中。

如果集合中根本不存在bar,那么每个人都认为你正在尝试添加吧。

我怀疑你采用了Python构造并错误移植了它。

答案 6 :(得分:0)

已解决

我在coredata对象枚举中遇到同样的问题。

不要更改依赖于运行循环的ARRAY的子对象

就像,如果我在On循环中更改/修改对象..它将给出此错误

 for (LoadList *objLL in ArrLoadList) {             // here Enumaration is Going on
        // here i has removed objects in ArrLoadList and reassign the ArrLoadList .. 
        // it will gives me this error 
        // So Don't change the Main Array object 
 }