无法从Spritekit SKScene转到另一个UIViewController,XCODE8 / Swift

我完全坚持尝试从我的SpriteKit游戏的第5个和最后一个场景中执行一个segue到项目中的另一个View Controller(不是GameViewController,也不是根视图控制器)。

我尝试运行self.view!.window!.rootViewController!.performSegueWithIdentifier(“finalSegue”,sender:self),来自我的finalScene,但它确实什么都没做(行被触发,它读取正确的ViewController – 我检查“ print(self.view!.window!.rootViewController!)“控制台打印”segue读取“按照我的指示,在segue命令之后,作为检查,segue标识符是正确的,但没有任何反应)。

尝试调用一个从GameViewController(我正在启动5个SKScenes的视图的视图控制器)执行segue的方法,我得到“在展开可选值时意外发现nil”。 尝试从最终场景(“finalScene.swift”)执行segue,同样的错误。

已经尝试了论坛中其他问题的所有相关解决方案,以及performSegue方法的“sender:”字段中nil / self / viewController的所有组合,但无济于事。 下面是我正在尝试的工作代码,它给出了“在展开可选值时意外发现nil”,指向viewController var,但在设备和模拟器上加载时给出了难以理解的调试。 似乎“nil”传递给我声明的viewController var,而不是原来的GameViewController?

我在Storyboard中的所有segue标识符都是正确的,所有内容都经过多次检查…我做错了什么? 我应该做一些与众不同的事情,鉴于它的第5个SKScene而不是第1个(如在其他解决方案中)? 通过从另一个UIViewController中划分到GameViewController中而进入SKScenes的工作正常 – 它们退出它们不起作用。 非常感谢任何帮助,完全停留在这里!

这是我的相关代码:

在我的GameViewController(启动我的5个连续SKScenes的UIViewController)中:

class GameViewController: UIViewController { let myScene = finalScene() override func viewDidLoad() { super.viewDidLoad() if let view = self.view as! SKView? { //this is the 1st out of 5 SKScenes in the project let scene = GameScene(size: CGSize(width: 2048, height: 2742)) //this is the 5th out of 5 scenes, that I am trying to trigger the segue out of myScene.viewController = self view.presentScene(scene) view.ignoresSiblingOrder = true } } } 

我是我的第五个场景,finalScene:

 class finalScene: SKScene { var viewController: GameViewController! override func touchesBegan(_ touches: Set, with event: UIEvent?) { for touch: AnyObject in touches{ let positionOfTouch = touch.location(in: self) let tappedNode = atPoint(positionOfTouch) let nameOfTappedNode = tappedNode.name if nameOfTappedNode == "continue" { self.viewController.performSegue(withIdentifier: "finalSegue", sender: self) } } } 

对于任何可能遇到此问题的人,我都是通过使用通知中心解决的。 即在游戏场景的父视图控制器上添加了一个通知观察者(它调用了一个执行segue的函数),并且在我想要做segue的游戏的终点,我发布了该通知,它的工作原理大。

在UIViewController的ViewDidLoad中添加观察者:

  override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(GameViewController.doaSegue), name: NSNotification.Name(rawValue: "doaSegue"), object: nil) } func doaSegue(){ performSegue(withIdentifier: "toNext", sender: self) self.view.removeFromSuperview() self.view = nil } 

然后从游戏SKScene中调用它:

 NotificationCenter.default.post(name: NSNotification.Name(rawValue: "doaSegue"), object: nil) 

您正在根viewController上调用segue。 我认为这就是问题所在。 你需要在场景的viewController上调用segue(我假设你已经创建了segue,因此它没有在根viewController上找到)。

现在问题是SKScene没有直接访问它的viewController,而只是它包含它的视图。 您需要手动创建指向它的指针。 这可以通过为SKScene创建属性来完成:

 class GameScene: SKScene { var viewController: UIViewController? ... } 

然后,在viewController类中,就在skView.presentScene(scene)之前

 scene.viewController = self 

现在,您可以直接访问viewController。 只需在此viewController上调用segue:

 func returnToMainMenu(){ self.viewController.performSegueWithIdentifier("menu", sender: vc) } 

发现这种方法同样适用。 但我更喜欢上面提到的方法,因为它的线数较少。 我不知道哪个更适合表现……