0

在我的 iphone 游戏中,在 ios 4.0 模拟器上运行时一切正常。但是,当使用 5.0 模拟器或 5.0+ 设备运行时,应用程序在第一级崩溃并留下错误:

由于未捕获的异常“NSGenericException”而终止应用程序,原因:
*** Collection <__NSArrayM: 0x1416eea0> 在枚举时发生了突变。
*** First throw call stack:
(0x1d6a052 0x20d0d0a 0x1d69c21 0x6f8e 0x8bd48 0x94020 0xba169 0xbcee4 0x85a2db 0x85a1af 0x1d3e966 0x1d3e407 0x1ca17c0 0x1ca0db4 0x1ca0ccb 0x2702879 0x270293e 0x90fa9b 0x1f31 0x1eb5 0x1)
terminate called throwing an exception(lldb)

我认为我已经将问题缩小到这段代码。我知道问题是在 for 循环中删除对象,但似乎无法找到解决方案。

这是我的代码:

//remove the projectile

for (CCSprite *projectile in projectilesToDelete) {
    [_projectiles removeObject:projectile];
    [self removeChild:projectile cleanup:YES];
}       
[projectilesToDelete release];

//remove the projectile

for (CCSprite *targetDel in targetsToDelete) {  
    targetDel.position = ccp(-2000, -2000);
    [self removeChild:targetDel cleanup:YES];
    [_targets removeObject:targetDel];
}                        
[targetsToDelete release];

请帮忙,这几天一直在想办法。

4

2 回答 2

2

简而言之,表达式:

for (OBJ * VAR in COLLECTION) {

使用一种称为快速枚举的技术。这里发生的是编译器在堆栈上插入一些隐藏的后备存储,并从可以枚举的类型中请求一组元素。因为它一次抓取许多对象并对其进行迭代,所以COLLECTION在枚举容器时改变容器 () 是错误的,因为堆栈区域和集合可能会不同步。

解决方法是在您更改要枚举的内容时避免快速枚举 - 要么这样,要么在某些情况下您可以枚举副本。标准for(i;c;e)循环不使用快速迭代——但for(in)确实使用了它。


改变程序以避免快速枚举错误的一种方法是:

// remove the projectile
while (projectilesToDelete.count) {
    CCSprite * projectile = projectilesToDelete[0];
    [_projectiles removeObject:projectile];
    [self removeChild:projectile cleanup:YES];
}
[projectilesToDelete release];

// remove the projectile
while (targetsToDelete.count) {
    CCSprite * targetDel = targetsToDelete[0];
    targetDel.position = ccp(-2000, -2000);
    [self removeChild:targetDel cleanup:YES];
    [_targets removeObject:targetDel];
}
[targetsToDelete release];
于 2012-08-27T06:37:44.810 回答
1

你的代码的问题是,考虑这个..... projectilesToDelete 数组有 3 个元素(A,B,C)......

在第一次迭代中,您 removeObject(A).. 在该数组计数变为 2 时,即数组内容将为 (B, C) 但它认为它是 3(B,C, Nil)。

所以 Array 在枚举时被修改了。所以它会给出一个例外。

将代码更改为此

// get array length
int count = projectilesToDelete. length;

// iterate through the array    
for (int iter = 0; iter < count; inter++) 
{
     CCSprite *projectile = projectilesToDelete [iter];

     [_projectiles removeObject:projectile];

     [self removeChild:projectile cleanup:YES];

      // decrement count
      count--;
      iter--;
} 
于 2012-08-27T06:29:26.913 回答