¿Es seguro cambiar `SKNode`s en un método de acción de reconocimiento de gestos?

Apple afirma en https://developer.apple.com/documentation/spritekit/skscenedelegate :

La modificación de objects SpriteKit fuera de las devoluciones de llamada orderadas (una queue de background o cualquier otra cosa que no sea hilo principal) puede ocasionar problemas relacionados con la concurrency. Incluso distribuir trabajos en el hilo principal de forma asíncrona o posterior es arriesgado, ya que es probable que el cierre se realice fuera del marco de time que espera SpriteKit. Si experimenta una falla de segmentación u otro tipo de falla que ocurre en el marco de SpriteKit, es muy probable que su código modifique un object SpriteKit fuera de las devoluciones de llamada normales.

Estoy usando reconocedores de gestos para interactuar con mis objects de kit de sprite. Un ejemplo simple sería agregar una SKAction a un nodo cuando el usuario tocó un object:

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

A pesar de que esto "funciona" por el momento, me temo que esto no funciona en casos más complicados.

¿Hay algún indicio de Apple de que esto está permitido? ¿O tengo que diferir la modificación del object SpritKit de la acción gestual a una devolución orderada?

Parece que estás a salvo, solo estás asignando una acción. Eso se ejecutará durante las actualizaciones normales del kit de sprites

si estuvieras manipulando el object real o eliminando un nodo, tendrías problemas. Digamos que toca para eliminar un nodo. Este toque sucede exactamente antes de didContactBegin . didContactBegin esperaría un nodo, pero por desgracia, lo eliminó, por lo que se bloqueará.

Si desea sentirse seguro al respecto, configure una queue para disparar al comienzo de su actualización.

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

Mis disculpas si esto no funciona la primera vez, ahora no estoy en una Mac para probar esto.