2016-03-08 27 views
2

我想知道從GameScene中訪問UIViewController方法的最佳做法是什麼。現在我一直在使用NSNotificationCenter,但由於我試圖實現的特定功能,我不想使用它。另外,如果沒有任何其他方法通過GameScene獲得對UIViewController的訪問權限,那麼我真正想知道的是能夠在不帶UIViewController的情況下在GameScene中呈現UIAlertController的方法。Swift SpriteKit:在GameScene中訪問UIViewController的最佳實踐

我只是爲UIViewController創建一個全局變量,但我聽說這是不好的做法。

謝謝!

回答

1

您可以顯示在SKScenes UIAlertControllers,只是表明他們在RootViewController的,這可能是反正他們展示的最佳場所。

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

我不喜歡在SKScenes引用GameViewController,我從來沒有真正得到了,我是被迫這樣做的一個點。 NSNotificationCenter,委託或協議擴展是更好的方法。

實際上,我使用Swift 2的協議擴展所使用的Alerts幫助程序,因爲我喜歡乾淨,可重用且儘可能少的重複代碼。

只是做一個新的.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") 

好像它們是場景本身的一部分。

享受

+0

這非常好,迫不及待地嘗試這個擴展。 – Electric

+0

我的榮幸。我喜歡它的靈活性,假設你現在製作的應用程序不是遊戲,只需將擴展名更改爲「.....其中Self:UIViewController。{」,現在您可以在所有視圖中顯示警報控制器。也許有一天,我們甚至可以添加2件事情,我認爲這是不可能的,就像「......自我:UIViewController,SKScene {」 – crashoverride777

+0

是的,靈活性非常好,方便。這也幫助我瞭解使用協議/擴展的好處。給了我一些關於如何在我的項目的其他部分簡化我的代碼的想法。感謝您的好評! – Electric

0

這是一個有點哈克,而是直接從視圖控制器使用這種訪​​問功能:

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

這依賴於你的SKView是在您的視圖控制器主視圖。如果不是,那麼您需要在view?呼叫後添加.superview?

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

感謝您的迴應!我會測試這些,並讓你知道哪些更好! – Electric

+0

檢查我的答案,有比鏈接到GameViewController更好的方法。如果需要,您甚至可以直接在SKScenes中顯示警報。不需要對ViewController的引用。 – crashoverride777