Search code examples
iosswiftuiviewcontrollersprite-kitskscene

How to pause SKScene from SKView or ViewController


I have the following code to pause game scene:

class GameProcessScene: SKScene {
...
var onPause: Bool = false {
    willSet {
        self.paused = newValue
        self.view?.paused = newValue
    }
}
...
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    for touch in touches {
        let location = touch.locationInNode(self)
        let possiblePauseNode = self.nodeAtPoint(location)
        if (possiblePauseNode.name == "pauseButton") {
            if (self.paused) {
                onPause = false
            } else {
                onPause = true
            }
            return
        }
    ...
    }
}

It works to pause by pressing button. But i also want to pause game when it appears from background. I am trying to do this from ViewController class:

override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "pauseGameScene", name: UIApplicationWillEnterForegroundNotification, object: nil)
}
func pauseGameScene() {
    let view = self.view as SKView
    let scene = view.scene
    switch scene {
    case is MainMenuScene:
        println("MainMenu")
    case let game as GameProcessScene:
        game.onPause = true
    default:
        println("default")
    }
}
deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

But it doesnt work when game appears from background. Can anybody help? Thanks!

UPD1: Also tried UIApplicationWillResignActiveNotification, UIApplicationDidEnterBackgroundNotification but game.onPause = true still doesnt work. It changes "SKScene.paused" property to true, but the actions are still executing when game enters foreground, even game scene was paused before it goes background.

UPD2: I moved observers and selectors from ViewController class to GameProcessScene: SKScene class - same effect, "paused" property changes, but in fact gameplay is continuing.


Solution

  • I solved my problem by creating a property called isPaused and overriding the paused property to always follow the isPaused property. Note : This disables the SKSCene from automatically pausing when going to background mode. You have to manually set the isPaused property. So only use it in scenes where you actually need the pause mode on resume.

    class GameScene: SKScene,SKPhysicsContactDelegate {
    
           // Initializers
    
        var isPaused : Bool = false {
            didSet {
                self.paused = isPaused
            }
        }
         override var paused : Bool {
            get {
                return isPaused
            }
            set {
                super.paused = isPaused
            }
        }
    }
    

    In ViewController

    override func viewDidLoad() {
        super.viewDidLoad()
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "pauseGameScene", name: UIApplicationWillResignActiveNotification, object: nil)
    }
    
    func pauseGameScene() {
        println("will become inactive")
        let view = self.view as SKView
        let scene = view.scene
        switch scene {
        case let game as GameScene:
            game.isPaused = true
        default:
            println("default")
        }
    }