2011-12-10 17 views
7

Soy relativamente nuevo en obj-c, así que me debería estar perdiendo algo, pero mi programa se bloquea cuando un enemigo colisiona con una pared. He localizado dónde estoy eliminando al enemigo del bucle, mientras estoy en el bucle, pero durante toda mi vida, no puedo encontrar la manera de solucionarlo. Mi código es el siguiente:Colección <__ NSArrayM: 0x76c11b0> se mutó mientras se enumeraba

(el error es "[allEnemies RemoveObject: enemyType1];")

// siempre corriendo - (void) actualización (ccTime) dt {

for (CCSprite *enemyType1 in allEnemies) { //for every attacking unit in allEnemies 

    //Adjust the collison box for each enemey depending on the height of the enemy 
    float a; 
    float b; 
    float yOne = (wall.contentSize.height-enemyType1.position.y); 
    float yTwo = (wall.contentSize.height); 
    float xTwo = 30; 
    a = (xTwo*(yOne/yTwo)); // always < 1 
    b = xTwo-a;    // always > 1 


    //Create the altered collison box 
    CGRect enemyType1Rect = CGRectMake (
       enemyType1.position.x - (enemyType1.contentSize.width/2), 
       enemyType1.position.y - (enemyType1.contentSize.height/2), 
       enemyType1.contentSize.width+b, 
       enemyType1.contentSize.height 
             ); 


    //If the enemey hits the wall, stop it, then add it to the attacking enemies array 
    if (CGRectIntersectsRect(enemyType1Rect, wall.boundingBox)) { 
     [enemyType1 stopAllActions]; 
     [allEnemies removeObject:enemyType1]; 
     [attackingEnemies addObject:enemyType1];    
    } 


} 
//Wall Collison END 

Respuesta

24

Bueno, al igual que el error indica, mutaste la matriz mientras estaba siendo enumerada. La solución más fácil es hacer for (CCSprite *enemyType1 in [[allEnemies copy] autorelease]). De esta manera está enumerando una copia de la matriz (esto NO copia los elementos, solo le da otro contenedor para enumerarlos), y aún puede modificar la matriz mutable.

No puede modificar contenedores al enumerarlos.

+0

bien, por lo que podría explicar por qué es exactamente lo que hace. ¿Hace [copia de AllEnemies] una copia de la matriz y la eliminará de la matriz original "allEnemies"? Además, cuando pones "autorelease" allí, no necesitas tener "[allEnemies removeObject: enemyType1];" ¿derecho? Lo siento si esto suena realmente tonto (acabo de obtener xcode 4 y esto me molestaba en 3). editar: Así que cambié ese fragmento de código y ahora obtengo: No se pudo registrar com.yourcompany.StromTheHouse con el servidor de arranque. Error: código de error desconocido. – user1091516

+0

Ok, xcode me odia. así que creo que recibo "por (CCSprite * enemyType1 en [[copia de AllEnemies] liberación automática])", y no obtengo el error de arranque, pero ahora cuando trato de probar en el dispositivo, aparece un nuevo error: StormTheHouse [11129: 707] cocos2d: No se pudo agregar la imagen: muro.png en CCTextureCache 2011-12-10 11: 02: 05.888 StormTheHouse [11129: 707] *** Error de aserción en - [HelloWorld addChild:], /Users/rauhul/Desktop/Invasion/libs/cocos2d/CCNode.m: 385 2011-12-10 11: 02: 05.890 StormTheHouse [11129: 707] *** Aplicación de finalización debido a la excepción no detectada 'NSInternalInconsistencyException', razón: 'Argumento debe ser no nulo' – user1091516

+0

nvm esas publicaciones me di cuenta de lo que era continuando, había hecho referencia a wall.png en mi código, pero las imágenes eran WALL.png, mucho menos – user1091516

4

El problema se encuentra dentro de esta línea de código: [allEnemies removeObject:enemyType1]; está enumerando una matriz allEnemies y la eliminación de un objeto de la matriz en la misma enumeración que está causando el problema. Debería usar una matriz temporal para el bucle mientras muta (removeObject:) la otra matriz.

0

También esto podría suceder cuando agrega un objeto a NSMutableArray y lee el registro de esa matriz. Y estas 2 tareas están sucediendo en dos hilos diferentes. Al igual que uno está sucediendo en el hilo de fondo y otro está pasando en el hilo principal. Así que ten cuidado con el enhebrado también.

2

No puede eliminar elementos de NSMutableArray mientras lo itera.

Hay varias soluciones a este:

  • Iterar una copia de la matriz

o

  • Utilice un for bucle basado en índices en lugar de la sintaxis for each.

no copiar la matriz que guarda una asignación y unos pocos ciclos de CPU:

for (int i = updatedLocalityArray.count-1 ; i >= 0 ; i--) 
{ 
    NSString *test = updatedLocalityArray[i]; 
    if ([test isEqualToString:tableViewCell.textLabel.text]) 
    { 
     [updatedLocalityArray removeObjectAtIndex:i]; 
     NSLog(@"%@ *****", updatedLocalityArray); 
    } 
} 
Cuestiones relacionadas