简体   繁体   English

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

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

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

I'm using gesture recognizers to interact with my sprite kit objects. 我正在使用手势识别器与我的精灵工具包对象进行交互。 A simple example would be to add a SKAction to a node when the user tapped an object: 一个简单的例子是当用户点击一个对象时向节点添加一个SKAction:

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

Despite the fact that this "just works" for the moment, I'm afraid that this does not work in more complicated cases. 尽管这一点“暂时正常”,但我担心这在更复杂的情况下不起作用。

Is there any hint from Apple that this is allowed? 苹果有任何暗示这是允许的吗? Or do I really have to defer the modification of the SpritKit object from the gesture action to an ordained callback? 或者我是否真的必须将SpritKit对象的修改从手势动作推迟到规定的回调?

It looks like you are safe, you are just assigning an action. 看起来你很安全,你只是分配一个动作。 That is going to run during the normal sprite kit updates 这将在正常的精灵套件更新期间运行

if you were manipulating the actual object, or removing a node, you would come into problems. 如果你正在操纵实际的对象,或删除一个节点,你会遇到问题。 Let's say you tap to remove a node. 假设你点击删除一个节点。 This tap happens right before didContactBegin . 这个点击发生在didContactBegin之前。 didContactBegin would expect a node, but alas, you removed it, so it will crash. didContactBegin会期望一个节点,但是唉,你删除它,所以它会崩溃。

If you want to feel safe about this, then set up a queue to fire at the beginning of your update. 如果您对此感到安全,请在更新开始时设置要触发的队列。

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))
    }}

}

My apologies if this does not run the first time, I am not on a Mac now to test this. 我很抱歉,如果这不是第一次运行,我现在不在Mac上测试这个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM