1

Explanation

My question is pretty straight forward: how do I print a variable from GameScene on GameViewController?


Code

I created this code below so it's easier to get the idea.

GameScene.swift

import SpriteKit

class GameScene: SKScene {

    var variable = Int()

    override func didMoveToView(view: SKView) {
        /* Setup your scene here */

        variable = 50
    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

        NSNotificationCenter.defaultCenter().postNotificationName("calledFromGameSceneVC", object: nil)
    }
}

GameViewController.swift

import UIKit
import SpriteKit

class GameViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Set view size.
        let scene = GameScene(size: view.bounds.size)

        // Configure the view.
        let skView = view as! SKView
        skView.showsFPS = true
        skView.showsNodeCount = true

        /* Sprite Kit applies additional optimizations to improve rendering performance */
        skView.ignoresSiblingOrder = true

        /* Set the scale mode to scale to fit the window */
        scene.scaleMode = .ResizeFill

        skView.presentScene(scene)

        //------------------------------//

        //Register observer
        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(GameViewController.calledFromGameScene), name: "calledFromGameSceneVC", object: nil)
    }

    func calledFromGameScene(){

        //Print variable
        let scene = GameScene(size: view.bounds.size)
        print("My variable from GameScene is: ", scene.variable)
    }
}


Sorry for the brief explanation.

Thanks in advance,
Luiz.

Luiz
  • 1,275
  • 4
  • 19
  • 35
  • 2
    `print("My variable from GameScene is: \(scene.variable)")` – Paulw11 Aug 02 '16 at 01:11
  • Both answers worked!! Thank you!! =) – Luiz Aug 02 '16 at 01:15
  • Sorry! I had to edit my question. I tried to print it from a function, but it's returning me 0, instead of 50 (`My variable from GameScene is: 0`). Did I do anything wrong? – Luiz Aug 02 '16 at 01:57
  • You are creating a new instance of `GameViewController`, so when you call `calledFromGameScene` it isn't using the instance you want. You should create a delegation protocol and have your game view controller implement that and then set itself as the game scene's delegate – Paulw11 Aug 02 '16 at 01:59
  • I tried to create this delegation protocol by following [this](http://stackoverflow.com/a/28187085/5802882) answer, but I kept getting many issues; so I used `NSNotificationCenter` to call the function in `GameScene`, as you can see in my question. But still, it's returning me 0 =( – Luiz Aug 02 '16 at 02:15
  • By moving the access into a separate function, you have lost the reference to the scene you have presented, so you are again creating a new game scene. This is not the scene you are looking for. You need to hold a reference to the scene you are presenting in a property of your view controller, but really delegation would be better – Paulw11 Aug 02 '16 at 02:38
  • So the only way is to create a delegation protocol as you said above? – Luiz Aug 02 '16 at 02:40
  • No, NSNotification will work, but you need to hold a reference to the scene you created in a property of your view controller – Paulw11 Aug 02 '16 at 02:41

1 Answers1

2

The type of inter-object communication you are trying to achieve is probably best addressed through a delegation pattern using a protocol:

GameScene.swift

import SpriteKit

protocol GameSceneDelegate {
    func calledFromGameScene(scene: GameScene)
}

class GameScene: SKScene {

    var variable = Int()

    var gameDelegate: GameSceneDelegate?

    override func didMoveToView(view: SKView) {
        /* Setup your scene here */

        variable = 50
    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {    
        gameDelegate?.calledFromGameScene(self)
    }
}

GameViewController.swift

class GameViewController: UIViewController, GameSceneDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Set view size.
        let scene = GameScene(size: view.bounds.size)

        // Configure the view.
        let skView = view as! SKView
        skView.showsFPS = true
        skView.showsNodeCount = true

        /* Sprite Kit applies additional optimizations to improve rendering performance */
        skView.ignoresSiblingOrder = true

        /* Set the scale mode to scale to fit the window */
        scene.scaleMode = .ResizeFill


        /* Set the delegate */
        scene.gameDelegate = self

        skView.presentScene(scene)
    }

    func calledFromGameScene(scene:GameScene){
        //Print variable
        print("My variable from GameScene is: ", scene.variable)
    }
}

Note that you can't use the property name delegate on your GameScene as SKScene already has a delegate property

Paulw11
  • 108,386
  • 14
  • 159
  • 186
  • Thank you sooooooo much!! It worked great. I was trying to understand this for weeks. Thanks!! =) – Luiz Aug 02 '16 at 03:07