Swift SpriteKit: Best practice to access UIViewController in GameScene [closed]

痞子三分冷 提交于 2019-12-24 01:19:58

问题


I wanted to see what the best practice(s) of accessing UIViewController methods from GameScene is/are. Right now I have been using NSNotificationCenter, but I don't want to use this due to specific functionality that I am trying to achieve.

Also, if there are not any other ways of gaining access to UIViewController through GameScene, then really what I am wondering is a method of being able to present an UIAlertController within the GameScene without UIViewController.

I would just create a global variable to the UIViewController, but I heard this is bad practice.

Thanks!


回答1:


You can show UIAlertControllers in SKScenes, simply show them on the rootViewController, which is probably the best place to show them anyway.

self.view?.window?.rootViewController?.present...

I dont like referencing the GameViewController in SKScenes and I never actually got to a point where I was forced to do so. NSNotificationCenter, delegation or protocol extensions are the better way.

I actually use a helper for Alerts I made using Swift 2's protocol extensions because I like clean, reusable and as little duplicate code as possible.

Just make a new .swift file and add this code

import SpriteKit

protocol Alerts { }
extension Alerts where Self: SKScene {

func showAlert(title title: String, message: String) {

    let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)

    let okAction = UIAlertAction(title: "OK", style: .Cancel) { _ in }
    alertController.addAction(okAction)

    self.view?.window?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)
}

func showAlertWithSettings(title title: String, message: String) {

    let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert)

    let okAction = UIAlertAction(title: "OK", style: .Cancel) { _ in }
    alertController.addAction(okAction)

    let settingsAction = UIAlertAction(title: "Settings", style: .Default) { _ in

        if let url = NSURL(string: UIApplicationOpenSettingsURLString) {
            UIApplication.sharedApplication().openURL(url)
        }
    }
    alertController.addAction(settingsAction)

    self.view?.window?.rootViewController?.presentViewController(alertController, animated: true, completion: nil)
    }
}

Now in your scenes you need to show alerts you simply conform to the protocol

class GameScene: SKScene, Alerts {

} 

and call the methods like

showAlert(title: "Alert title", message: "Alert message")

as if they are part of the scene itself.

Enjoy




回答2:


This is a bit hacky, but to directly access functions from the view controller use this:

(view?.nextResponder() as? MyViewController)?.presentAlert()

This relies upon your SKView being the main view in your view controller. If it isn't then you'll need to add in .superview? after your view? call.




回答3:


An alternative to the previous answer I posted (and the more proper method) would be to create a property in your scene class to store a reference to the view controller and use that:

class MyGameScene: SKScene {

    weak var viewController: MyViewController?

    func somethingHappened() {
        viewController?.presentAlert()
    }

}

And when you present the scene in your controller make sure to set a reference to your view controller:

if let scene = GameScene(fileNamed:"GameScene") {
    scene.viewController = self

    // other stuff
    skView.presentScene(scene)
}


来源:https://stackoverflow.com/questions/35875674/swift-spritekit-best-practice-to-access-uiviewcontroller-in-gamescene

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!