2011-12-10 15 views
7

Sono relativamente nuovo a obj-c, quindi mi manca qualcosa, ma il mio programma si arresta quando un nemico entra in collisione con un muro. Ho individuato dove sto rimuovendo il nemico dal ciclo, mentre nel ciclo, ma per la vita di me, non riesco a capire come risolverlo. mio codice è il seguente:La raccolta <__ NSArrayM: 0x76c11b0> è stata modificata mentre è elencata

(l'errore è "[allEnemies RemoveObject: enemyType1];")

// sempre in funzione - (void) aggiornamento: (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 

risposta

24

Bene, proprio come dice l'errore, si è mutato l'array mentre veniva enumerato. La soluzione più semplice da fare è for (CCSprite *enemyType1 in [[allEnemies copy] autorelease]) In questo modo si enumera una copia dell'array (questo NON copia gli elementi, ti dà solo un altro contenitore per enumerarli) e può ancora modificare l'array mutabile.

Non è possibile modificare i contenitori durante l'enumerazione.

+0

ok, quindi Ci può spiegare che cosa esattamente che fa. [AllEnemies copy] crea una copia dell'array e lo rimuoverà dalla matrice originale "allEnemies". Inoltre, quando si inserisce "autorelease", non è necessario avere "[allEnemies removeObject: enemyType1];" destra? Scusa se questo suona davvero stupido (ho appena ricevuto xcode 4 e non di questo mi dava fastidio il mio in 3). modifica: Così ho cambiato quel pezzo di codice e ora ottengo: Impossibile registrare com.yourcompany.StromTheHouse con il server di bootstrap. Errore: codice di errore sconosciuto. – user1091516

+0

Ok, xcode mi odia. quindi penso di ottenere "per (CCSprite * enemyType1 in [[allEnemies copy] autorelease])", e non ottengo l'errore di bootstrap, ma ora quando provo a testare su Device, ottengo un nuovo errore: StormTheHouse [11129: 707] cocos2d: Impossibile aggiungere l'immagine: wall.png in CCTextureCache 2011-12-10 11: 02: 05.888 StormTheHouse [11129: 707] *** Errore asserzione in - [HelloWorld addChild:], /Users/rauhul/Desktop/Invasion/libs/cocos2d/CCNode.m: 385 2011-12-10 11: 02: 05,890 StormTheHouse [11129: 707] *** Terminazione dell'app a causa di eccezione non rilevata 'NSInternalInconsistencyException', motivo: 'Argomento deve essere non nullo' – user1091516

+0

nvm quei post ho capito cosa era andando avanti, avevo fatto riferimento a wall.png nel mio codice ma le immagini erano WALL.png, Thx soooo molto – user1091516

4

Il problema si trova in questa riga di codice: [allEnemies removeObject:enemyType1]; si sta enumerando un array allEnemies e si rimuove un oggetto dall'array nello stesso enumerazione che causa il problema. È necessario utilizzare un array temporaneo per il loop durante la mutazione (removeObject:) dell'altro array.

0

Anche questo potrebbe accadere quando si aggiunge un oggetto in NSMutableArray e si legge il record da tale array. E questi 2 compiti stanno accadendo in due thread diversi. Come succede uno nel thread in background e ne sta succedendo un altro sul thread principale. Così attento anche alla filettatura.

2

Non è possibile eliminare elementi da NSMutableArray durante l'iterazione.

Ci sono diverse soluzioni per questo:

  • Iterate una copia della matrice

o

  • Usare un ciclo for indice a base anziché la sintassi for each.

Non copiare l'array consente di risparmiare una dotazione e un paio di cicli di 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); 
    } 
} 
Problemi correlati