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

Kla*_*aas 3 multithreading gestures uigesturerecognizer ios sprite-kit

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

修改受约束的回调之外的SpriteKit对象(后台队列或任何其他非主线程)可能导致与并发相关的问题.即使异步或稍后在主线程上调度工作也存在风险,因为关闭很可能是在SpriteKit期望的时间范围之外完成的.如果您遇到SpriteKit框架内部发生的分段错误或其他类型的崩溃,那么您的代码很可能会在正常回调之外修改SpriteKit对象.

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

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

尽管这一点"暂时正常",但我担心这在更复杂的情况下不起作用.

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

Kni*_*gon 5

看起来你很安全,你只是分配一个动作.这将在正常的精灵套件更新期间运行

如果你正在操纵实际的对象,或删除一个节点,你会遇到问题.假设你点击删除一个节点.这个点击发生在之前didContactBegin. didContactBegin会期望一个节点,但是唉,你删除它,所以它会崩溃.

如果您对此感到安全,请在更新开始时设置要触发的队列.

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


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

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

}
Run Code Online (Sandbox Code Playgroud)

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