C 风格的 for 循环工作正常但更改为 Swift for-in 会导致越界错误

C-Style for loop works fine but changing to Swift for-in causes out of bounds errors

所以我有这个简单的 for 循环,这让我很生气。看,它使用 C 风格的 for 循环(已注释)工作得很好。但是 swift 会发出警告(不是错误),表明 C 样式循环将来会被贬值,所以我认为我应该更改它。

然而,当我尝试更改它时,我得到了一个 out of bounds 错误,这在 C-Style 循环中从未发生过。错误发生在 if 语句处(因此仅当鼠标悬停在奶酪上时)。而且我不明白为什么它应该使用 C 循环而不是 for-in 循环。

func checkCheese(){
    //for(var i = 0; i < cheese.count; i += 1){
    for i in 0 ..< cheese.count {
        print(i) //prints just fine every time
        if CGRectIntersectsRect(mouse.node.frame, cheese[i].node.frame) {//throws the out of bounds error
            cheese[i].node.removeFromParent() 
            cheese.removeAtIndex(i) //the culprit?
        }
    }
}

如有任何帮助,我们将不胜感激。

如果可能,我还想解释为什么循环的行为不同。 谢谢

cheese.count 仅被评估一次。假设您从 cheese 中的 3 个项目开始。循环将遍历索引 012。如果删除项目 1,则旧的 2 会变成新的 1,并且索引 2 处不再有项目。但是,循环将继续索引 2,就像它从一开始就打算做的那样。

要解决此问题,请在每次删除时递减索引:

for i in 0 ..< cheeses.count {
    print(i) //prints just fine every time
    if CGRectIntersectsRect(mouse.node.frame, cheeses[i].node.frame) {//throws the out of bounds error
        cheeses[i].node.removeFromParent() 
        cheeses.removeAtIndex(i) //the culprit? ... no longer!
        i -= 1 //fixed!
    }
}

现在,这解决了您提出的解决方案的错误,但我提出了一个更清晰的解决方案:

cheeses.filter{ cheese in
          if CGRectIntersectsRect(mouse.node.frame, cheese.node.frame {
              cheese.node.removeFromParent()
              return false //don't keep this cheese
          }
          else {
              return true //keep this cheese          
          }
      }