Swift SpriteKit: лучшая практика для доступа к UIViewController в GameScene
Я хотел посмотреть, каковы лучшие методы доступа к методам UIViewController из GameScene. Прямо сейчас я использую NSNotificationCenter, но я не хочу использовать это из-за определенных функций, которые я пытаюсь достичь.
Кроме того, если нет других способов получить доступ к UIViewController через GameScene, то на самом деле меня интересует способ представления UIAlertController в GameScene без UIViewController.
Я бы просто создал глобальную переменную для UIViewController, но я слышал, что это плохая практика.
Спасибо!
3 ответа
Вы можете показывать UIAlertControllers в SKScenes, просто показывать их в rootViewController, который, пожалуй, является лучшим местом для их отображения в любом случае.
self.view?.window?.rootViewController?.present...
Мне не нравится ссылаться на GameViewController в SKScenes, и я никогда не доходил до того момента, когда меня заставляли это делать. 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")
как будто они являются частью самой сцены.
наслаждаться
Альтернативой предыдущему ответу, который я разместил (и более правильный метод), будет создание свойства в вашем классе сцены для хранения ссылки на контроллер представления и использование этого:
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)
}
Это немного странно, но для прямого доступа к функциям из контроллера представления используйте это:
(view?.nextResponder() as? MyViewController)?.presentAlert()
Это зависит от того, является ли ваш SKView основным видом в вашем контроллере представления. Если это не так, вам нужно добавить в .superview?
после вашего view?
вызов.