Swift SpriteKit:在GameScene中访问UIViewController的最佳实践

时间:2016-03-08 18:55:47

标签: ios swift uiviewcontroller sprite-kit

我想看看从GameScene访问UIViewController方法的最佳实践是什么。现在我一直在使用NSNotificationCenter,但由于我想要实现的特定功能,我不想使用它。

此外,如果没有任何其他方式可以通过GameScene获取对UIViewController的访问权限,那么我真正想知道的是能够在没有UIViewController的情况下在GameScene中呈现UIAlertController的方法。

我只是为UIViewController创建一个全局变量,但我听说这是不好的做法。

谢谢!

3 个答案:

答案 0 :(得分:1)

你可以在SKScenes中展示UIAlertControllers,只需在rootViewController上显示它们,这可能是最好的展示它们的地方。

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

我不喜欢在SKScenes中引用GameViewController,而我实际上从未达到过被迫这样做的地步。 NSNotificationCenter,委托或协议扩展是更好的方法。

我实际上使用了一个使用Swift 2协议扩展的警报的助手,因为我喜欢干净,可重用和尽可能少的重复代码。

只需创建一个新的.swift文件并添加此代码

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)
    }
}

现在,在您的场景中,您需要显示符合协议的警报

class GameScene: SKScene, Alerts {

} 

并调用类似

的方法
showAlert(title: "Alert title", message: "Alert message")

好像他们是场景本身的一部分。

享受

答案 1 :(得分:0)

这有点hacky,但要从视图控制器直接访问函数,请使用:

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

这取决于您的SKView是视图控制器中的主视图。如果不是,那么您需要在.superview?来电后添​​加view?

答案 2 :(得分:0)

我发布的上一个答案(以及更合适的方法)的替代方法是在场景类中创建一个属性来存储对视图控制器的引用并使用它:

class MyGameScene: SKScene {

    weak var viewController: MyViewController?

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

}

当您在控制器中显示场景时,请确保设置对视图控制器的引用:

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

    // other stuff
    skView.presentScene(scene)
}