tim_yng
tim_yng

Reputation: 2671

how to present UIViewController from SKScene

Usaly when you present a viewController from another viewController you do:

let vc : UIViewController = storyboard.instantiateViewControllerWithIdentifier("viewController") as UIViewController;
self.presentViewController(vc, animated: true, completion: nil);

I want to present a viewController from a SKScene. I haven't found any way of doing that. This question might be a duplicate, but i have just found answers in objective C that doesn't make sense to me

Upvotes: 4

Views: 3267

Answers (2)

Coder ACJHP
Coder ACJHP

Reputation: 2224

Briefly -> You can't present a ViewController from SKScene directly but...

Today i was trying to solve this problem, in my game i need to present my PayWallViewController, UIAlertViewController, UIReferenceLibraryViewController and actually didn't find any documentation about this case.

After thinking & googling couple of hours i found few methods to solve the problem and decided to share them here. Each method has its strengths and potential drawbacks, depending on your specific needs and the complexity of your project.

  1. Holding a reference of your ViewController inside the Scene:

It allows you to direct access without the need for intermediaries and faster then other methods but may cause memory management problems & less modular and harder to maintain

Example Code:

In your scene declare vc reference (weak)

class GameScene: SKScene {
    weak var gameViewController: GameViewController?

    override func didMove(to view: SKView) {
        // Use vc reference any where as you wish
    }

    override func willMove(from view: SKView) {
        // Release resources
        gameViewController = nil
    }
}

An then then your view controller:

import UIKit
import SpriteKit

class GameViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        if let skView = self.view as? SKView {
            let scene = GameScene(size: skView.bounds.size)
            scene.gameViewController = self // Assign you vc here
            skView.presentScene(scene)
            skView.ignoresSiblingOrder = true
        }
    }
}
  1. Using NotificationCenter:

Promotes loose coupling, allowing better separation of concerns, more flexible easy to broadcast to multiple listeners if needed and don't need to block the main thread. At the same time slightly slower then other methods and hard to debug

Example Code:

GameViewController.swift: Observe notification that comes from GameScene

override func viewDidLoad() {
    super.viewDidLoad()
    if let skView = self.view as? SKView {
        let scene = GameScene(size: skView.bounds.size)
        skView.presentScene(scene)
    }
    NotificationCenter.default.addObserver(self, selector: #selector(presentAlert), name: NSNotification.Name("PresentAlert"), object: nil)
}

@objc func presentAlert() {
    let alert = UIAlertController(title: "Alert", message: "This is an alert.", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
    present(alert, animated: true, completion: nil)
}

// Don’t forget to remove observer
deinit {
    NotificationCenter.default.removeObserver(self)
}

GameScene.swift: Post notification when you need

func triggerAlert() {
    NotificationCenter.default.post(name: NSNotification.Name("PresentAlert"), object: nil)
}
  1. Block-based Communication:

Maintains loose coupling with clear communication paths, more flexible and readable but it needs to well document

Example Code:

var onRequestAlert: (() -> Void)? // Add it in your scene and call it when you need
scene.onRequestAlert = { [weak self] in self?.presentAlert() } // listen to trigger inside your ViewController

Upvotes: 0

Endre Olah
Endre Olah

Reputation: 955

Try the following in your scene class:

var currentViewController:UIViewController=UIApplication.sharedApplication().keyWindow.rootViewController!

currentViewController.presentViewController(viewController, animated: true, completion: nil)

I hope it helps.

Upvotes: 9

Related Questions