ios - SpriteKit - enumerateChildNode 导致崩溃 "array was mutated while being enumerated."

标签 ios swift multithreading sprite-kit

我正在玩弄一些 SpriteKit 的东西。我是 SpriteKit 的新手,所以我的技术可能不好,我不知道。这是我正在做的事情:

它基本上是一艘带护盾的宇宙飞船(2D,从上方看)。有几个“屏蔽段”(左、右、上、下,每个都是一个 SKShapeNode),然后是“移相器”节点,它们是从中绘制的线设备中心的边界(宇宙飞船在中心)。我想检测相位器何时击中其中一个护盾部分。我使用 collisionMasks 尝试了这个,但它根本不起作用。所以我尝试了自己的检测方式。

接下来,我绘制移相器的方法可能看起来很奇怪。我在网上搜索但没有找到任何东西,真的。因此,我绘制移相器的方法是不断用每帧稍长的路径替换 移相器节点(一条直线)的路径。

这是执行此操作并导致应用程序崩溃的方法:

incomingPhasers 是一个包含当前场景中所有 Phaser 对象的数组。 Phaser类主要包含名为nodeSKShapeNode和其他一些元信息。

phaser progress 的推进是通过将 progress 属性增加一点来完成的。 delta 是自上一帧以来的时间差(因为此方法是从 update(_:)

调用的)

let vector 是用于画线的位移矢量。

private func advancePhasers(_ delta: TimeInterval) {
    for phaser in incomingPhasers where !phaser.targetHit {
        // advance progress of phaser
        phaser.progress = min(phaser.progress + CGFloat(delta) * phaser.progressRate, 1)
        let vector = phaser.origin.vector(toPoint: phaser.target, fraction: phaser.progress)

        // create new path
        let path = UIBezierPath()
        path.move(to: phaser.origin)
        path.addLine(to: phaser.origin + vector)
        phaser.node.path = path.cgPath

        // check collision
        let phaserPoint = path.currentPoint
        enumerateChildNodes(withName: "shieldSegment", using: { (node, stop) in
            if let node = node as? ShieldSegmentNode {
                if node.contains(phaserPoint) {

                    // collision
                    phaser.targetHit = true

                }
            }
        })
    }
}

enumerateChildNodes 当我向数组添加许多移相器时导致应用程序崩溃:

* Terminating app due to uncaught exception 'NSGenericException', reason: '* Collection <__NSArrayM: 0x17404ce40> was mutated while being enumerated.'

我不确定我能在这里做什么。我必须循环遍历屏蔽段节点,但这一直在崩溃。

这跟线程安全有关系吗?我需要让它线程安全吗?如果是,怎么办?

谢谢!

如果您需要更多信息或代码,请告诉我。我不能在这里发布所有内容,代码太多了。

最佳答案

在枚举集合时,您不能更改(更改、添加或删除项目)集合。如果没有代码中的更多详细信息,很难告诉您更多有关如何修复它的信息。有些东西正在改变这里的集合:

enumerateChildNodes(withName: "shieldSegment", using: { (node, stop) in
    if let node = node as? ShieldSegmentNode {
        if node.contains(phaserPoint) {

            // collision
            phaser.targetHit = true

        }
    }
})

我解决这些问题的一种方法是我有第二个集合,用于将项目放入符合我所需标准的项目,然后在第一次枚举之后,我可以枚举第二个集合并对第一个集合执行必要的突变

关于ios - SpriteKit - enumerateChildNode 导致崩溃 "array was mutated while being enumerated.",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44531725/

相关文章:

ios - Swift - 如何获取当前时间(以秒为单位)?

ios - iCarousel 无限滚动和索引重置

ios - WKInterfaceTable 中的部分

ios - 如何将固定的 SCNNode 附加到 ARKit 的 pointOfView?

java - 如何最有效地从多个线程访问共享文件?

c# - 线程、事件和 GUI

JavaScript 下拉列表 : Select onClick

ios - Alamofire "installation"不工作(嵌入式二进制文件中的红色文本)

ios - 删除 firebase 中的对象

python - 有没有办法在 Windows 上使用 32 位 python 2.7 从线程中打开 64 位 exe?