Question

i have a strange issue , if i remove my item at forin enumeration , it would crash , so like this:

for (Obstacle *obstacleToTrack in _obstaclesToAnimate) {
    //this if else not so important for happening crash
    if(obstacleToTrack.distance > 0){
        obstacleToTrack.distance -= _playerSpeed * _elapsed;
    }else{
        if (obstacleToTrack.watchOut) {
            obstacleToTrack.watchOut = NO;
        }
        obstacleToTrack.x -= (_playerSpeed + obstacleToTrack.speed) * _elapsed;
    }
    if (obstacleToTrack.x < -obstacleToTrack.width || _gameState == GS_OVER) {
        [self removeChild:obstacleToTrack];
        //this line makes crash happen , if remove this line code work fine
        [_obstaclesToAnimate removeObject:obstacleToTrack];
    }
}

if i change my code to

NSMutableArray *forRemoving = [[NSMutableArray alloc]init];
for (Obstacle *obstacleToTrack in _obstaclesToAnimate) {
    //this if else not so important for happening crash
    if(obstacleToTrack.distance > 0){
        obstacleToTrack.distance -= _playerSpeed * _elapsed;
    }else{
        if (obstacleToTrack.watchOut) {
            obstacleToTrack.watchOut = NO;
        }
        obstacleToTrack.x -= (_playerSpeed + obstacleToTrack.speed) * _elapsed;
    }
    if (obstacleToTrack.x < -obstacleToTrack.width || _gameState == GS_OVER) {
        // code change here
        [self removeChild:obstacleToTrack];
        [forRemoving addObject:obstacleToTrack];
    }
}
for(Obstacle *obstacleToTrack in forRemoving){
    [_obstaclesToAnimate removeObject:obstacleToTrack];
    [forRemoving removeObject:obstacleToTrack];
}
[forRemoving release];

this would work perfect , could someone tell me why?

Was it helpful?

Solution

The answer is that if you remove an object the other objects in that array move postion in the array since an item is removed.

For example we have an array with 4 items, if we remove the first item (item 0) the item that used to be at index 1 is now at index 0 and the item at 2 is now at 1. Thus the enumeration breaks.

You could solve this by looping thru the array from the count down to 0:

for (int i = [array count]-1; i >= 0; i--) {
    id object = [array objectAtIndex:i];

    if (some check) {
       [array removeObjectAtIndex:i];
    }
}

OTHER TIPS

Like rckoenes said, you break the enumaration by removing stuff in the array while iterating through it.

What you can do is to have a second array where you insert the objects that you want to remove. Then, after your enumeration is finished you can remove all the objects that are found in the second array, from your first array.

You must not modify a collection while iterating through its items.

If you iterate index based (i.e. the classical for loop), you can remove things, but be careful about adjusting your index.

Check this link

https://developer.apple.com/library/mac/documentation/cocoa/conceptual/Collections/Articles/Enumerators.html

Enumeration is “safe”—the enumerator has a mutation guard so that if you attempt to modify the collection during enumeration, an exception is raised.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top