iosswiftsprite-kitskview

How to move from UIViewController to SKView and vice versa?


My idea is showing map for few seconds before moving to game scene and the game screens hierarchy is like this:

GameViewController(UIViewController) -> EntryToGameScene (SKView) -> MapController (UIViewController) -> GamePlayGround (SKView)

I'm facing with a problem when moving from MapController to GamePlayGround, to be able to move from controller to scene at first I changed controllers view class to SKView from Storyboard then I added following code ⬇️.After handleDelay() method is running, game scene didMove() method working but the screen stucking on old view (MapController)!? I'm sure game scene didMove() method working because background music starts to play.But why screen is not change?

My code is looks like :

override func viewDidLoad() {
    super.viewDidLoad()
    // Wait for three sec. then move to game scene
    self.perform(#selector(handleDelay), with: nil, afterDelay: 3.0)
}

@objc fileprivate func handleDelay() {

    view.layoutIfNeeded()

    if let view = self.view as! SKView? {
        // Load the SKScene
        let scene = GameScene(size: sceneSize)

        // Set the scale mode
        scene.scaleMode = .aspectFill
        scene.delegate = self
        // Present the scene
        view.presentScene(scene)

        view.ignoresSiblingOrder = true
        view.showsFPS = false
        view.showsNodeCount = false
        view.showsPhysics = false
    }
}

All answers acceptable.


Solution

  • The solution with removing all subviews from the view then presenting SKScene.

    Note: I know its not the best solution but there is no another choise for now, so I changed my code like this:

    override func viewDidLoad() {
        super.viewDidLoad()
    
        self.perform(#selector(handleDelay), with: nil, afterDelay: 3.0)
    
    }
    
    @objc fileprivate func handleDelay() {
    
        self.view.subviews.forEach {$0.removeFromSuperview()}
    
        if let view = self.view as! SKView? {
            // Load the SKScene from 'GameScene.swift' and should set it's size
            let scene = SecondGameScene(size: self.view.frame.size)
            // Set the scale mode to scale to fit the window
            scene.scaleMode = .aspectFill
    
            // Present the scene
            view.presentScene(scene)
    
            view.ignoresSiblingOrder = true
    
            view.showsFPS = false
            view.showsNodeCount = false
        }
    
    }
    

    UPDATE : Finally I found right way for moving from SKScene and UIView Controller and vice versa.

    For example (Moving from SKScene to UIViewController):

    fileprivate func moveToUIViewController(storyBoardId: String) {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let vc = storyboard.instantiateViewController(withIdentifier: storyBoardId)
        vc.view.frame = self.frame
        vc.view.layoutIfNeeded()        
    
        self.view?.window?.rootViewController?.present(vc, animated: true, completion: nil)
    }
    

    (Moving from UIViewController to SKScene):

    fileprivate func returnToSKScene() {
    
        for element in self.view.subviews {
            element.removeFromSuperview()
        }
        self.dismiss(animated: true) {
            if let view = self.view as! SKView? {
                // Load the SKScene
                var scene: SKScene
                scene = AboutScene(size: sceneSize)
    
                // Set the scale mode
                scene.scaleMode = .aspectFill
                let transition = SKTransition.moveIn(with: .up, duration: 0.2)
    
                // Present the scene
                view.presentScene(scene, transition: transition)
    
                view.ignoresSiblingOrder = true
                view.showsFPS = false
                view.showsNodeCount = false
                view.showsPhysics = false
    
            }
        }
    }
    

    Don't forget to change UIViewController view class with "SKView":

    1. Select view the from Storyboard -> Identity inspector -> Custom class.

    2. 2.Select SKView from Class dropdown list.