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

时间:2017-07-13 12:26:26

标签: ios multithreading sprite-kit uigesturerecognizer gestures

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

  

在规定的回调之外修改SpriteKit对象(a   可以导致后台队列或其他任何非主线程)   并发相关问题。 甚至在主线程上调度工作   异步或稍后是有风险的,因为关闭是   可能是在SpriteKit期望的时间范围之外完成的。如果   您遇到了分段错误或其他类型的崩溃   发生在SpriteKit框架深处,这是一个很好的机会   你的代码正在修改普通的SpriteKit对象   回调。

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

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

尽管这个"正常运作"目前,我担心这在更复杂的情况下不起作用。

Apple是否允许这样做?或者我是否真的必须将SpritKit对象的修改从手势动作推迟到规定的回调?

1 个答案:

答案 0 :(得分: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))
    }}

}

如果第一次没有运行,我很抱歉,我现在不在Mac上测试它。