# Crash due to removal of Elements like CCSprite from NSMutableArray

So, here's how it goes.

I am currently working on Cocos2d game, which consists of many Obstacles. One obstacle gets added on the screen at an interval of 10 seconds like this.

ObstacleSprite* newObstacle = [ObstacleSprite spriteWithFile:@"Obstacle.png" rect:CGRectMake(0, 0, 20, 20)];
newObstacle.position = ccp(mainPlayer1.position.x,10);



Now, I insert these obstacles into the arrayForObstacles because I also want to keep checking whether the Obstacles and MainPlayer don't collide.

I check it with the help of this function.

- (void) checkCollisionWithObstacle
{
if(mainPlayer1.playerActive)
{
for(int  i = 0; i < [self.arrayForObstacles count]; i++)
{
ObstacleSprite* newObstacle = [self.arrayForObstacles objectAtIndex:i];
if(newObstacle != nil)
{
if(CGRectIntersectsRect([mainPlayer1 boundingBox], [newObstacle boundingBox]))
{
mainPlayer1.livesLeft--;
}
}
}
}
}


THE ISSUE

Problem is when I get to certain score, one of the Obstacles gets deleted. Removal of Obstacles works as in First In-First Out (FIFO) mode. So, to delete obstacles, I write the following method :

- (void) keepUpdatingScore
{
//update new score
mainPlayer1.score+=10;
//remove obstacle when score increases by 5k
if(mainPlayer1.score > 5000 && mainPlayer1.score > 0)
{
mainPlayer1.playerActive = NO;

if([self.arrayForObstacles count] > 0)
{
CCLOG(@"count is %d",[self.arrayForObstacles count]);
ObstacleSprite* newObstacle = [self.arrayForObstacles objectAtIndex:0];
[self.arrayForObstacles removeObjectAtIndex:0];
[self removeChild:newObstacle cleanup:YES];

CCLOG(@"count is %d",[self.arrayForObstacles count]);
}
}
else
{

}
}


It crashes when score crosses 5000 mark!

UPDATE

Crash happens when it again goes to the method checkCollisionWithObstacle.

THis is the line Which crashes.

You may have already figured this out.

I had this same issue. For me that problem was that I was enumerating through an array of objects, such as an array of enemy ship objects, and trying to delete one of those objects before the enumeration had completed.

For example. If while looping through the array I found that an enemy was colliding with an asteroid I would then delete the enemy from the array. Let’s say for the sake of argument that my array had 20 enemy ships in it, and while enumerating through it I found that ship 12 hit an asteroid and needed to be destroyed and thus deleted. I could delete the object from the array without any problem, but then the app would crash as soon as it resumed enumerating through the array to check on ships 13 through 20. It didn’t like the fact that I had just deleted an object from an array that it had not finished looping through.

So, if at some point within your game loop you are enumerating through that obstacle array and you end up trying to delete one of those obstacles before that enumeration is finished, this could be the cause of your crash.

• Yep, it was a similar problem. I was deleting an element from the array but there was another thread where this array was getting enumerated continuously. had fixed this long time back. But thanks for the help! :) – mayuur Nov 29 '12 at 18:17
• I figured you had taken care of it, but thought I would respond for the benefit of anyone else who ran into the same problem. :) – Pluvius Nov 30 '12 at 2:01

Could be a number of things.

For one thing this won't fix anything but it'll make your code easier to follow, you don't have to do for (int i etc.)

for(ObstacleSprite *temp in self.arrayForObstacles)


does what you did in 3 lines in 1.

This makes no sense

mainPlayer1.score > 5000 && mainPlayer1.score > 0

If mainPlayer1.score > 5000 its greater than 0. So I guess it does make sense I just don't see the point.

And finally...

ObstacleSprite* newObstacle = [self.arrayForObstacle objectAtIndex:0];
[self.arrayForObstacles removeObjectAtIndex:0];
[self removeChild:newObstacle cleanup:YES];


You set newObstacle to an object in an array then you remove the object from the array then you remove it from it's parent. Don't do that.