0

I've implemented a protocol to get some sort of message, that a game has already finished and passes the time to my controller (Game wrote in SpriteKit). But now I'm having this fatal error after finishing the game and executing the gameEnded method and the app just crashes. Does anyone know why?

Here is my code

GameViewController

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!###
}

Here is my other 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)
}

EDIT: I did all the things that you told me to, and it still crashes at the same point. Xcode told me to use a delegate. When I do delegate? It works, but that's not what I want. That function has to be called!

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

I've put in some println() in the prepareForSegue() methods, but somehow they won't get executed. Do I have to call them somehow? Here is a screenshot of my segue.

https://i.sstatic.net/oK4Ce.png

I also tried putting in one segue the other way round, but it doesn't help either.

https://i.sstatic.net/TVmdP.png (no identifier because it's the only segue.)

I forgot to say that the SpriteKit Game behind this AcceleratorGameController calls the gameOver() method when it has finished.

2 Answers 2

2

First of all, some tips :

  • Always try to declare your protocols (when refer to the delegate pattern) in the following way:

    protocol GameEnded : class {
        func gameHasFinished(time: Float)
    }
    

    With the above way you can then, declare your delegate variable weak and avoid a strong reference.

  • You class weak var should be in the following way:

    class AcceleratorGameController: UIViewController {
    
       weak var delegate : GameEnded?
    
       // rest of your code
    }
    

And for the last you should keep a reference as a global variable of the class AcceleratorGameController to set as your delegate in the prepareForSegue, like in the following way:

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

And the above code should be fix your issue. I hope this help you.

Sign up to request clarification or add additional context in comments.

4 Comments

Why would we have to worry about weak/strong references? I thought ARC was supposed to remove our need to worry about that.
Yes, and no it could exist retain cycles, you can read more about it in the answer of @matt in this stackoverflow.com/questions/27327545/….
Yes that makes it clearer. I will have to remember this when adopting the delegate pattern.
i edited the question with ur tips but it still doesnt work
1

I don't see how ChallengeViewController will initialize the delegate of AccelerometerGameController.

In your prepareForSegue, you are setting the delegate for the GameController only if the segue identifier is accelGane. But when firing the segue in showAccelGameView, you are not using this identifier. If you already have the segue setup in your storyboard, use this to fire the segue

self.performSegueWithIdentifier("accelGane", sender: self)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.