"fatal error: unexpectedly found nil while unwrapping an Optional value" while calling a protocol method
"fatal error: unexpectedly found nil while unwrapping an Optional value" while calling a protocol method
我已经实现了一个协议来获取某种消息,游戏已经完成并将时间传递给我的控制器(在 SpriteKit 中编写的游戏)。但是现在我在完成游戏并执行 gameEnded 方法后遇到了这个致命错误,应用程序崩溃了。有谁知道为什么?
这是我的代码
游戏ViewController
class AcceleratorGameController: UIViewController {
var time: Float = 0.0
var challengeController: ChallengeViewController!
weak var delegate : GameEnded?
override func viewDidLoad() {
super.viewDidLoad()
if let scene = AcceleratorGame.unarchiveFromFile("AcceleratorGame") as? AcceleratorGame {
let skView = self.view as! SKView
skView.showsFPS = true
scene.viewController = self
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var dest : ChallengeViewController = segue.destinationViewController as! ChallengeViewController
dest.gameHasFinished(time) //Dont know if this does anything...
println("Segue now!")
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(true)
println("View will disapear")
delegate.gameHasFinished(self.time) // ###CRASHES HERE!###
}
这是我的另一个ViewController
protocol GameEnded : class {
func gameHasFinished(time: Float)
}
class ChallengeViewController : UIViewController, GameEnded {
var time : Float = 0.0
var acceleratorGameController : AcceleratorGameController!
override func viewDidLoad() {
super.viewDidLoad()
println("ChallengeViewController geladen")
startGame()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "accelGame" {
acceleratorGameController = segue.destinationViewController as! AcceleratorGameController
acceleratorGameController.delegate = self
}
}
func startGame () {
println("Start Game")
self.showAccelGameView()
}
func gameHasFinished(time: Float) {
println("Game has finished")
self.time = time
}
func showAccelGameView() {
println("Show Accel Game")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("AcceleratorGameController") as! AcceleratorGameController
self.navigationController?.pushViewController(vc, animated: true)
}
编辑:
我做了你告诉我的所有事情,但它仍然在同一点崩溃。 Xcode 告诉我使用委托。我什么时候做委托?它有效,但这不是我想要的。必须调用该函数!
func gameOver(time: Float) {
println("Game Over")
self.time = time
//delegate!.gameHasFinished(time) still crashes here. added !. i commented it to test the prepareForSegue method
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var dest : ChallengeViewController = segue.destinationViewController as! ChallengeViewController
dest.gameHasFinished(time)
println("Segue now!") // Wont happen
self.navigationController?.popViewControllerAnimated(true) //Wont happen either. If i call this in gameOver() it works.
}
我在 prepareForSegue()
方法中加入了一些 println()
,但不知何故它们不会被执行。我必须以某种方式给他们打电话吗?这是我的 segue 的截图。
http://i.stack.imgur.com/oK4Ce.png
我也试过把一个 segue 反过来,但也没用。
http://i.stack.imgur.com/TVmdP.png(没有标识符,因为它是唯一的 segue。)
我忘了说这个 AcceleratorGameController
背后的 SpriteKit Game 在完成时调用了 gameOver()
方法。
首先,一些提示:
始终尝试以下列方式声明您的协议(当参考 delegate 模式时):
protocol GameEnded : class {
func gameHasFinished(time: Float)
}
通过上述方式,您可以声明 delegate
变量 weak
并避免强引用。
你classweak var
应该是这样的:
class AcceleratorGameController: UIViewController {
weak var delegate : GameEnded?
// rest of your code
}
最后,您应该将 class AcceleratorGameController
的引用作为全局变量,以便在 prepareForSegue
中设置为您的 delegate
,就像在以下方式:
class ChallengeViewController : UIViewController, GameEnded {
var acceleratorGameController : AcceleratorGameController!
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "accelGane" {
acceleratorGameController = segue.destinationViewController as! AcceleratorGameController
acceleratorGameController.delegate = self
}
}
}
上面的代码应该可以解决您的问题。希望对你有帮助。
我不明白 ChallengeViewController
将如何初始化 AccelerometerGameController
的委托。
在您的 prepareForSegue
中,您仅在 segue 标识符为 accelGane
时才为 GameController 设置委托。但是在 showAccelGameView
中触发 segue 时,您没有使用此标识符。如果你的故事板中已经有 segue 设置,使用它来触发 segue
self.performSegueWithIdentifier("accelGane", sender: self)
我已经实现了一个协议来获取某种消息,游戏已经完成并将时间传递给我的控制器(在 SpriteKit 中编写的游戏)。但是现在我在完成游戏并执行 gameEnded 方法后遇到了这个致命错误,应用程序崩溃了。有谁知道为什么?
这是我的代码
游戏ViewController
class AcceleratorGameController: UIViewController {
var time: Float = 0.0
var challengeController: ChallengeViewController!
weak var delegate : GameEnded?
override func viewDidLoad() {
super.viewDidLoad()
if let scene = AcceleratorGame.unarchiveFromFile("AcceleratorGame") as? AcceleratorGame {
let skView = self.view as! SKView
skView.showsFPS = true
scene.viewController = self
skView.ignoresSiblingOrder = true
scene.scaleMode = .AspectFill
skView.presentScene(scene)
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var dest : ChallengeViewController = segue.destinationViewController as! ChallengeViewController
dest.gameHasFinished(time) //Dont know if this does anything...
println("Segue now!")
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(true)
println("View will disapear")
delegate.gameHasFinished(self.time) // ###CRASHES HERE!###
}
这是我的另一个ViewController
protocol GameEnded : class {
func gameHasFinished(time: Float)
}
class ChallengeViewController : UIViewController, GameEnded {
var time : Float = 0.0
var acceleratorGameController : AcceleratorGameController!
override func viewDidLoad() {
super.viewDidLoad()
println("ChallengeViewController geladen")
startGame()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "accelGame" {
acceleratorGameController = segue.destinationViewController as! AcceleratorGameController
acceleratorGameController.delegate = self
}
}
func startGame () {
println("Start Game")
self.showAccelGameView()
}
func gameHasFinished(time: Float) {
println("Game has finished")
self.time = time
}
func showAccelGameView() {
println("Show Accel Game")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("AcceleratorGameController") as! AcceleratorGameController
self.navigationController?.pushViewController(vc, animated: true)
}
编辑: 我做了你告诉我的所有事情,但它仍然在同一点崩溃。 Xcode 告诉我使用委托。我什么时候做委托?它有效,但这不是我想要的。必须调用该函数!
func gameOver(time: Float) {
println("Game Over")
self.time = time
//delegate!.gameHasFinished(time) still crashes here. added !. i commented it to test the prepareForSegue method
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var dest : ChallengeViewController = segue.destinationViewController as! ChallengeViewController
dest.gameHasFinished(time)
println("Segue now!") // Wont happen
self.navigationController?.popViewControllerAnimated(true) //Wont happen either. If i call this in gameOver() it works.
}
我在 prepareForSegue()
方法中加入了一些 println()
,但不知何故它们不会被执行。我必须以某种方式给他们打电话吗?这是我的 segue 的截图。
http://i.stack.imgur.com/oK4Ce.png
我也试过把一个 segue 反过来,但也没用。
http://i.stack.imgur.com/TVmdP.png(没有标识符,因为它是唯一的 segue。)
我忘了说这个 AcceleratorGameController
背后的 SpriteKit Game 在完成时调用了 gameOver()
方法。
首先,一些提示:
始终尝试以下列方式声明您的协议(当参考 delegate 模式时):
protocol GameEnded : class { func gameHasFinished(time: Float) }
通过上述方式,您可以声明
delegate
变量weak
并避免强引用。你class
weak var
应该是这样的:class AcceleratorGameController: UIViewController { weak var delegate : GameEnded? // rest of your code }
最后,您应该将 class AcceleratorGameController
的引用作为全局变量,以便在 prepareForSegue
中设置为您的 delegate
,就像在以下方式:
class ChallengeViewController : UIViewController, GameEnded {
var acceleratorGameController : AcceleratorGameController!
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "accelGane" {
acceleratorGameController = segue.destinationViewController as! AcceleratorGameController
acceleratorGameController.delegate = self
}
}
}
上面的代码应该可以解决您的问题。希望对你有帮助。
我不明白 ChallengeViewController
将如何初始化 AccelerometerGameController
的委托。
在您的 prepareForSegue
中,您仅在 segue 标识符为 accelGane
时才为 GameController 设置委托。但是在 showAccelGameView
中触发 segue 时,您没有使用此标识符。如果你的故事板中已经有 segue 设置,使用它来触发 segue
self.performSegueWithIdentifier("accelGane", sender: self)