user1091516
user1091516

Reputation: 93

Collection <__NSArrayM: 0x76c11b0> was mutated while being enumerated

I'm relatively new to obj-c, so I must be missing something, but my program crash when an enemy collides with a wall. I've located where I'm removing the enemy from the loop, while in the loop, but for the life of me, i can't figure out how to fix it. My code is as follows:

(the error is "[allEnemies removeObject:enemyType1];")

//ALWAYS RUNNING -(void) update:(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

Upvotes: 8

Views: 12635

Answers (4)

Pawan Ahire
Pawan Ahire

Reputation: 199

You cannot delete items from a NSMutableArray while iterating it.

There are several solutions to this:

  • Iterate a copy of the array

or

  • Use an index-based for loop instead of the for each syntax.

Not copying the array saves you an allocation and a few CPU cycles:

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

Upvotes: 2

A K M Saleh Sultan
A K M Saleh Sultan

Reputation: 2403

Also this could be happen, when you are adding an object into NSMutableArray and reading record from that array. And these 2 tasks are happening in two different thread. Like one is happening in background thread and another one is happening on main thread. So careful about the threading as well.

Upvotes: 0

Saurabh Passolia
Saurabh Passolia

Reputation: 8109

The problem lies within this line of code: [allEnemies removeObject:enemyType1]; you are enumerating an array allEnemies and removing an object from the array in the same enumeration which is causing the issue. You should use a temp array for the looping while actually mutating(removeObject:) the other array.

Upvotes: 4

Joshua Weinberg
Joshua Weinberg

Reputation: 28688

Well, just as the error states, you mutated the array while it was being enumerated. The easiest fix is to do for (CCSprite *enemyType1 in [[allEnemies copy] autorelease]) This way you're enumerating a copy of the array (this does NOT copy the elements, just gives you another container to enumerate them in), and can still modify the mutable array.

You can not modify containers while enumerating them.

Upvotes: 24

Related Questions