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

我想看看从GameScene访问UIViewController方法的最佳做法是什么。 现在我一直在使用NSNotificationCenter,但是我不想使用这个,因为我想要实现的特定function。

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

我只是创build一个全局variables的UIViewController,但我听说这是不好的做法。

谢谢!

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

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

我不喜欢在SKScenes中引用GameViewController,而且我从来没有真正到过一个我被迫这样做的地步。 NSNotificationCenter,委托或协议扩展是更好的方法。

实际上,我使用Swift 2的协议扩展提供的帮助,因为我喜欢干净,可重用,尽可能less的重复代码。

只需创build一个新的.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") 

就好像它们是场景本身的一部分一样。

请享用

这有点不好意思,但直接从视图控制器访问函数使用这个:

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

这依赖于你的SKView是视图控制器中的主视图。 如果不是,那么你需要添加.superview?view? 呼叫。

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

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