用于删除NSMutableArray崩溃中的项目的快速枚举

Jef*_*ang 2 objective-c nsmutablearray fast-enumeration

我有一个奇怪的问题,如果我在forin枚举中删除我的项目,它会崩溃,所以像这样:

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];
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我改变我的代码

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];
Run Code Online (Sandbox Code Playgroud)

这会很完美,有人可以告诉我为什么吗?

rck*_*nes 5

答案是,如果删除对象,则该数组中的其他对象会移动数组中的位置,因为项目已被删除.

例如,我们有一个包含4个项目的数组,如果我们删除第一个项目(项目0),那么以前在索引1的项目现在在索引0处,而在2处的项目现在是1.因此枚举中断.

您可以通过将数组从倒计时循环到0来解决此问题:

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

    if (some check) {
       [array removeObjectAtIndex:i];
    }
}
Run Code Online (Sandbox Code Playgroud)

  • `[array count]` 返回数组中的项数,但是可以传递给 `[array objectAtIndex:]` 的最大索引是 `[array count]-1`,因此在第一次传递时会崩溃。正确的代码是:`for (int i = [array count]-1; i &gt;= 0; i--) { ...` (2认同)