【问题标题】:Why is init(coder:) being called when I provide an init() function为什么在我提供 init() 函数时调用 init(coder:)
【发布时间】:2017-05-24 18:40:21
【问题描述】:

我正在使用 SpriteKit,并且正在加载一个 SceneKit 文件,该文件包含许多带有自定义类的精灵。场景实际上从未加载,因为它到达第一个自定义类并从 required init?(coder:) 初始化程序中抛出 fatalerror。虽然自定义类实现了一个初始化器,但我无法确定为什么它选择该初始化器而不是我提供的初始化器。

自定义类:

class Bat: SKSpriteNode, GameSprite {
  var initialSize: CGSize = CGSize(width: 44, height: 24)
  var textureAtlas: SKTextureAtlas = SKTextureAtlas(named: "Enemies")
  var flyAnimation = SKAction()

  init() {
    super.init(texture: nil, color: .clear, size: initialSize)

    self.physicsBody = SKPhysicsBody(circleOfRadius: size.width / 2)
    self.physicsBody?.affectedByGravity = false

    createAnimations()
    self.run(flyAnimation)
  }

  required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }

  func createAnimations() {
    let flyFrames: [SKTexture] = [textureAtlas.textureNamed("bat"),
                                  textureAtlas.textureNamed("bat-fly")]

    let flyAction = SKAction.animate(with: flyFrames, timePerFrame: 0.12)
    flyAnimation = SKAction.repeatForever(flyAction)
  }

  func onTap() {}
}

下面是尝试加载场景然后循环遍历子元素并初始化它们的代码:

遭遇经理:

class EncounterManager {
  // Store encounter file names
  let encounterNames: [String] = [
    "EncounterA"
  ]

  // Each encounter is a node, store an array
  var encounters: [SKNode] = []

  init() {
    // Loop through each encounter scene and create a node for the encounter
    for encounterFileName in encounterNames {
      let encounterNode = SKNode()

      // Load the scene file into a SKScene instance and loop through the children
      if let encounterScene = SKScene(fileNamed: encounterFileName) {
        for child in encounterScene.children {

          // Create a copy of the scene's child node to add to our encounter node
          // Copy the position, name, and then add to the encounter
          let copyOfNode = type(of: child).init()
          copyOfNode.position = child.position
          copyOfNode.name = child.name
          encounterNode.addChild(copyOfNode)
        }
      }

      // Add the populated encounter node to the array
      encounters.append(encounterNode)
    }
  }

  // This function will be called from the GameScene to add all the encounter nodes to the world node
  func addEncountersToScene(gameScene: SKNode) {
    var encounterPosY = 1000

    for encounterNode in encounters {
      // Spawn the encounters behind the action, with increasing height so they do not collide
      encounterNode.position = CGPoint(x: -2000, y: encounterPosY)
      gameScene.addChild(encounterNode)

      // Double Y pos for next encounter
      encounterPosY *= 2
    }
  }
}

我注意到使用断点是它永远不会超过加载场景。它在if let encounterScene = SKScene(fileNamed: encounterFileName) 行失败,错误是 Bat 类的初始化程序中的致命错误。

任何帮助理解为什么它选择一个初始化器而不是另一个将不胜感激!

【问题讨论】:

  • 谢谢马丁!楼在下面的回答也解释了这一点,我将为其他登陆这里的人接受这一点。感谢您快速准确的回复!

标签: swift swift3 sprite-kit skspritenode


【解决方案1】:

你正在做:

 if let encounterScene = SKScene(fileNamed: encounterFileName)

调用 SKScene 的 init(fileNamed:) 加载文件并使用 SKScene 的 coder init 对其进行解码。该初始化加载文件并使用节点的编码器初始化解码其中的每个元素。

如果要从文件加载,需要实现coder init。

【讨论】:

  • 谢谢娄,我会在允许的时候接受这个。我将尝试将其设置为 convenience 初始化程序,然后从其中调用我的自定义 init 方法,看看是否可以修复它。我实际上不知道它已存档,然后在加载期间取消存档。
  • 我会调用 super 来取消归档基本属性。
  • 其实你是对的 Lou,当你实际加载遭遇时它会有所帮助哈哈,但所有内容都通过super.init(coder: aDecoder) 调用完美加载
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-17
相关资源
最近更新 更多