Ios Swift SpriteKit:在游戏场景中访问UIViewController的最佳实践
我想看看从游戏场景访问UIViewController方法的最佳实践是什么。现在我一直在使用NSNotificationCenter,但由于我正在尝试实现的特定功能,我不想使用它 此外,如果没有任何其他方式可以通过游戏场景访问UIViewController,那么我真正想知道的是一种能够在游戏场景中显示UIViewController而无需UIViewController的方法 我只想为UIViewController创建一个全局变量,但我听说这是一个糟糕的做法Ios Swift SpriteKit:在游戏场景中访问UIViewController的最佳实践,ios,swift,uiviewcontroller,sprite-kit,Ios,Swift,Uiviewcontroller,Sprite Kit,我想看看从游戏场景访问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的结构,现在它只是一个协议扩展。如果您感兴趣,我会稍微升级我的帮助器。语法有点旧,而且您也不必手动关闭警报控制器。