在手势识别器操作方法中更改 SKNode 是否安全?

Is it safe to change `SKNode`s in a gesture recognizer action method?

Apple 在 https://developer.apple.com/documentation/spritekit/skscenedelegate 中声明:

Modifying SpriteKit objects outside of the ordained callbacks (a background queue or anything else non-main-thread) can result in concurrency related problems. Even dispatching work on the main thread asynchronously or at a later time is risky because the closure is likely to be done outside of the timeframe SpriteKit expects. If you're experiencing a segmentation fault or other type of crash occurring deep within the SpriteKit framework, there's a good chance your code is modifying a SpriteKit object outside of the normal callbacks.

我正在使用手势识别器与我的 sprite 工具包对象进行交互。一个简单的示例是在用户点击对象时向节点添加 SKAction:

func tapAction(gr:UITapGestureRecognizer) {
    scene.childNode(withName: "balloon")!.run(SKAction.fadeOut(withDuration: 2))
}

尽管目前"just works",但恐怕这在更复杂的情况下不起作用。

苹果有没有暗示这是允许的?或者我真的必须将 SpritKit 对象的修改从手势动作推迟到指定的回调吗?

看来你是安全的,你只是在分配一个动作。在正常的 sprite 工具包更新期间 运行

如果您要操纵实际对象或删除节点,就会遇到问题。假设您点击以删除一个节点。这次点击恰好发生在 didContactBegin 之前。 didContactBegin 本来希望有一个节点,但是,唉,你删除了它,所以它会崩溃。

如果您想对此感到安全,请设置一个队列以在更新开始时触发。

class GameScene : SKScene
{
   public typealias Closure = ()->()
   public var processOnUpdate = [Closure]()


   override func update(_ currentTime: TimeInterval) {
       proceseOnUpdate.forEach{[=10=]()}
       processOnUpdate = [Closure]()
       ....//do other stuff
   }
}

//SKView Code
func tapAction(gr:UITapGestureRecognizer) {
    scene.processOnUpdate.append(
    { 
       scene.childNode(withName: "balloon")!.run(SKAction.fadeOut(withDuration: 2))
    }}

}

抱歉,如果这不是第一次 运行,我现在不在 Mac 上进行测试。