Coder1000
Coder1000

Reputation: 4461

How can I dismiss a ViewController from my GameScene.swift?

QUESTION: How can I dismiss a ViewController from my GameScene.swift ?


SITUTATION: I have 2 VCs in my SpriteKit Game, like so:

ViewController.swift ----Press Play-----> GameViewController

When the player loses, I want to dismiss the GameViewController so the player can press play again. I check for the player's loss in my GameScene.swift and would like to dismiss the GameVC from there.


N.B.: Googled this without success.


WHAT I TRIED:

1) Creating a gameVC instance in my GameScene.swift and dismissing it like so:

let gameVC = GameViewController()
gameVC.dismissViewController(false,completion: nil)

2) Doing:

self.view.window!.rootViewController?.dismissViewControllerAnimated(false, completion: nil)

Those don't work for obvious reasons ^^

Upvotes: 2

Views: 1224

Answers (2)

Alessandro Ornano
Alessandro Ornano

Reputation: 35392

I've follow some of your discussion. I want to add some code, because usually I prefeer to work with one ViewController or two and many SKScene and SKNode, but in this case could be useful to have a currentViewController reference:

class MyModelScene: SKScene {
   let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
   var currentViewController : MyModelViewController! = MyModelViewController() 
 // MyModelViewController is a customized UIViewController

   override func didMoveToView(view: SKView) {
      super.didMoveToView(view)
      print("---")
      print("∙ \(NSStringFromClass(self.dynamicType))")
      print("---")
   }
}

class Level1Scene: MyModelScene {
    ...
}

In the UIViewController:

class PreloadViewController: MyModelViewController {
     override func viewDidLoad() {
        super.viewDidLoad()

        if let scene = Level1Scene(fileNamed:"Level1Scene") {
            // Configure the view.
            let skView = self.view as! SKView
            skView.showsFPS = true
            skView.showsPhysics = true
            skView.showsNodeCount = true

            skView.ignoresSiblingOrder = true

            /* Set the scale mode to scale to fit the window */
            scene.scaleMode = .ResizeFill 
            scene.currentViewController = self
            skView.presentScene(scene)
        }
    }
}

With this code , you've always a currentViewController reference in your SKScene and you can check if it's the correct viewController you want to dismiss or not.

Upvotes: 1

Aaron Brager
Aaron Brager

Reputation: 66252

You don't want to "grab" the existing instance: https://pragprog.com/articles/tell-dont-ask

You need to either hand GameScene a reference to the view controller so it can dismiss it, or use the delegate pattern to communicate backwards to a controlling object that the VC should be dismissed/dismiss itself.

A simple example… you can add a GameViewController property to GameScene, then dismiss the VC at the appropriate time:

class GameScene: SKScene {
    var gameVC: GameViewController?

    func gameDidEnd() {
        gameVC?.dismissViewControllerAnimated(true) {
            // if desired, do any cleanup after the VC is dismissed
        }
    }
}

Then, just set this property when creating the GameScene object in the first place:

if let gameScene = GameScene(fileNamed: "MyScene") {
    gameScene.gameVC = someGameVC
}

This simple approach will tightly couple GameScene and GameViewController, making it a bit more difficult if you ever want to use one of these objects without the other. But for this simple use case, it may be fine.

Upvotes: 2

Related Questions