Ios Swift SpriteKit:在游戏场景中访问UIViewController的最佳实践

Ios Swift SpriteKit:在游戏场景中访问UIViewController的最佳实践,ios,swift,uiviewcontroller,sprite-kit,Ios,Swift,Uiviewcontroller,Sprite Kit,我想看看从游戏场景访问UIViewController方法的最佳实践是什么。现在我一直在使用NSNotificationCenter,但由于我正在尝试实现的特定功能,我不想使用它 此外,如果没有任何其他方式可以通过游戏场景访问UIViewController,那么我真正想知道的是一种能够在游戏场景中显示UIViewController而无需UIViewController的方法 我只想为UIViewController创建一个全局变量,但我听说这是一个糟糕的做法 谢谢 这有点老套,但要直接从视图

我想看看从游戏场景访问UIViewController方法的最佳实践是什么。现在我一直在使用NSNotificationCenter,但由于我正在尝试实现的特定功能,我不想使用它

此外,如果没有任何其他方式可以通过游戏场景访问UIViewController,那么我真正想知道的是一种能够在游戏场景中显示UIViewController而无需UIViewController的方法

我只想为UIViewController创建一个全局变量,但我听说这是一个糟糕的做法


谢谢

这有点老套,但要直接从视图控制器访问函数,请使用以下命令:

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

这取决于SKView是视图控制器中的主视图。如果不是,则需要在调用
视图?
后添加
.superview?

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

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

您可以在SKScenes中显示UIAlertController,只需在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")
好像它们是场景本身的一部分


享受

谢谢您的回复!我会测试这些,让你知道哪个更好!检查我的答案,有比链接到GameViewController更好的方法。如果需要,您甚至可以在场景中直接显示警报。不需要引用ViewController。这非常好,迫不及待地想尝试这个扩展。我的荣幸。我喜欢它的灵活性,比如说你现在制作了一个不是游戏的应用程序,你只需将扩展名改为“…where Self:UIViewController.{”,现在你可以在所有视图控制器上显示警报。也许有一天我们甚至可以在这个应用程序中添加两个东西,我认为这是不可能的,比如“…其中Self:UIViewController,SKScene{"是的,灵活性非常好而且非常方便。这也帮助我了解了使用协议/扩展的好处。给了我一些如何在我的项目的其他部分简化代码的想法。谢谢你的回复!是的,协议扩展真的很棒。过去几周我在我的项目中也做了同样的事情。如果你愿意的话为了查看另一个示例,我制作了一个社交共享帮助器。以前它是一个带有static func的结构,现在它只是一个协议扩展。如果您感兴趣,我会稍微升级我的帮助器。语法有点旧,而且您也不必手动关闭警报控制器。