在游戏套件中展开Optional值时意外地发现了nil

时间:2017-09-06 13:53:50

标签: ios swift sprite-kit gamekit

我只是尝试使用SKEmitterNode和SKSpriteNode 但我在我的代码的第二行收到错误

startfield.position = CGPoint.init(x:0,y:1200)

并且错误就像

  

“致命错误:在解开可选值时意外发现nil”

获得2次,也是这一次

  

“对于frZQaeyWLUvLjeuEK43hmg没有沙箱访问权限且未正确授权”

我不明白可选概念所以因为我无法解决它..

class GameScene: SKScene {

 var startfield : SKEmitterNode!
 var player : SKSpriteNode!

  override func didMove(to view: SKView) {
      startfield = SKEmitterNode(fileNamed: "Starfield")
      startfield.position = CGPoint.init(x: 0, y: 1200)
      startfield.advanceSimulationTime(10)
      self.addChild(startfield)
      startfield.zPosition = -1
        //define Player
    player = SKSpriteNode(imageNamed: "shuttle")
    player.position = CGPoint(x: self.frame.width/2, y: player.size.height/2 + 20)
    self.addChild(player)
  }

  override func update(_ currentTime: TimeInterval) {
      // Called before each frame is rendered
  }
}

3 个答案:

答案 0 :(得分:1)

重新声明您的starfield变量(错误输入为startfield?),以便它允许使用nil值:

var starfield: SKEmitterNode?

这是必要的,因为SKEmitterNode(fileNamed:)是可选的初始化工具,即。即一个可能会返回nil。在进一步使用此变量测试之前,如果不是nil,e。 G。使用guard声明:

guard let starfield = starfield else { return }

对于你的函数的其余部分starfield现在是非零的。

答案 1 :(得分:1)

该行:

startfield = SKEmitterNode(fileNamed: "Starfield")

如果找不到该文件,可以返回nil但是您将其存储在隐式展开的Optional中:

var startfield : SKEmitterNode!

因此,系统会将其视为非nil,但它确实是nil。然后,当您尝试为nil分配属性时:

startfield.position = CGPoint.init(x: 0, y: 1200)
// should really be: CGPoint(x: 0, y: 1200)

一切都爆炸了,你会遇到致命的错误。

相反,请检查文件是否正确加载,然后执行分配:

override func didMove(to view: SKView) {
  // Load the file into a `SKEmitterNode?` and use optional binding 
  // to attempt to unwrap into a `SKEmitterNode`.
  guard let emitter = SKEmitterNode(fileNamed: "Starfield") else {
    // Unwrapping failed, crash with an appropriate message.
    fatalError("File \"Starfield\" not found.")
  }
  // Unwrapping succeeded, continue
  startfield = emitter
  // ...
}

首先加载到SKEmitterNode?的原因是由于failable initializer继承自SKNode的{​​{3}}加载:init(fileNamed:)

convenience init?(fileNamed filename: String)

Optional Binding是指您使用构造if let来展开Optional

答案 2 :(得分:0)

当您在类型后面创建一个!的变量时,您可以使用#34;隐式展开"。实际上,这意味着如果变量为nil并且您尝试引用它,则会崩溃。

删除声明中的!

var startfield : SKEmitterNode?

然后更改你的didMove函数以使用一个警卫:

  override func didMove(to view: SKView) {
      startfield = SKEmitterNode(fileNamed: "Starfield")

      guard let startfield = startfield else {
         print("startfield is nil!")
         return
      }
      startfield.position = CGPoint.init(x: 0, y: 1200)
      startfield.advanceSimulationTime(10)
      self.addChild(startfield)
      startfield.zPosition = -1
        //define Player
    player = SKSpriteNode(imageNamed: "shuttle")
    player.position = CGPoint(x: self.frame.width/2, y: player.size.height/2 + 20)
    self.addChild(player)
  }