SKAction runAction 不执行完成块

SKAction runAction does not execute completion block

A SKSpriteNodeSKNode 的子项,出于存储目的放置在 SKSpriteNode 的数组中。

这个SKSpriteNode是用动画删除的。在此动画结束时,执行完成块以执行一些语句...

删除必须发生在 SKSpriteNode 父级和数组中。根据这 2 个删除的顺序,结果是否正确:

为什么会出现这种行为?

for position in listOfPositions {

   theSprite:SKSpriteNode = theGrid[position]

   /// the SKSpriteNode referenced by theSprite :
   /// - belongs to an array of SKSpriteNode: theGrid
   /// - belongs to a SKNode: theGameLayer
   ///
   /// In other words this SKSpriteNode is referenced twice
   ///

   let theActions = SKAction.sequence([
      /// Some actions here
      /// ...

      /// Remove theSprite from the Grid
      /// - position is an instance of a structure of my own
      /// - theGrid is accessed via a subscript
      ///
      SKAction.runBlock({self.theGrid[position] = nil}),

      /// remove theSprite from it's parent
      SKAction.removeFromParent(),
   ])

   theSprite.runAction(theActions,completion:{NSLog("Deleted")})
}

显示完成消息。

现在如果removeFromParent放在remove from theGrid动作之前,如下,补全不执行:

let theActions = SKAction.sequence([
   /// Some actions here
   /// ...

   /// remove theSprite from it's parent
   SKAction.removeFromParent(),

   /// remove theSprite from the Grid
   SKAction.runBlock({self.theGrid[position] = nil}),
])

来自SKAction Reference

An SKAction object is an action that is executed by a node in the scene (SKScene)...When the scene processes its nodes, actions associated with those nodes are evaluated.

换句话说,当且仅当该节点在场景中时,该节点的动作是运行。通过调用 removeFromParent,您从场景中移除节点,永远不会调用 runBlock 动作(因为节点不再在场景中),因此序列永远不会完成。由于序列未完成,因此不会调用完成块。

为了安全起见,我建议将 removeFromParent 调用移至完成块。这样的事情感觉更安全:

for position in listOfPositions {

   let theSprite: SKSpriteNode = theGrid[position]

   /// the SKSpriteNode referenced by theSprite :
   /// - belongs to an array of SKSpriteNode: theGrid
   /// - belongs to a SKNode: theGameLayer
   ///
   /// In other words this SKSpriteNode is referenced twice
   ///

   let theActions = SKAction.sequence([
      /// Some actions here
      /// ...

      /// Remove theSprite from the Grid
      /// - position is an instance of a structure of my own
      /// - theGrid is accessed via a subscript
      ///
      SKAction.runBlock({self.theGrid[position] = nil})
   ])

   theSprite.runAction(theActions) {
      /// remove theSprite from it's parent
      /// Might need to weakly reference self here
      theSprite.removeFromParent(),
      NSLog("Deleted")
   }
}

TL;DR
序列未完成,因此未调用序列的完成块。