我有一个奇怪的问题,如果我在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];
}
}
如果我将代码更改为
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];
这会很完美,有人可以告诉我为什么吗?
答案 0 :(得分: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];
}
}
答案 1 :(得分:3)
就像rckoenes所说的那样,你可以通过在迭代它时删除数组中的东西来打破这种想法。
您可以做的是在第二个数组中插入要删除的对象。然后,在枚举完成后,您可以从第一个数组中删除第二个数组中找到的所有对象。
答案 2 :(得分:1)
在迭代其项目时,不得修改集合。
如果基于索引进行迭代(即经典for循环),则可以删除内容,但要小心调整索引。
答案 3 :(得分:1)
检查此链接
枚举是“安全的” - 枚举器有一个变异防护,所以如果 您尝试在枚举期间修改集合,这是一个例外 被提出来了。