【问题标题】:Segue in SKScene to UIViewController在 SKScene 中转至 UIViewController
【发布时间】:2015-01-19 03:08:51
【问题描述】:

在我的 GameScene.swift 文件中,我试图像这样执行回到我的菜单视图控制器的 segue:

func returnToMainMenu(){
    var vc: UIViewController = UIViewController()
    vc = self.view!.window!.rootViewController!
    vc.performSegueWithIdentifier("menu", sender: vc)
}

该方法在节点被点击时运行:

override func touchesEnded(touches: NSSet, withEvent event: UIEvent) {
    for touch: AnyObject in touches {
        let location = touch.locationInNode(self)
        if gameOn == false{
            if restartBack.containsPoint(location){
                self.restartGame()
            }
            else if menuBack.containsPoint(location){
                self.returnToMainMenu()
            }
            else if justBegin == true{
                self.restartGame()
            }
        }
    }
}

menuBack 是返回菜单的按钮。每次我运行这段代码时,都会抛出一个 NSException:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver (<ProxyBlock.Menu: 0x165a3e90>) has no segue with identifier 'menu''

我检查了我的 segue 标识符,它确实是“菜单”。

【问题讨论】:

  • segue 用于从一个视图控制器到另一个视图控制器,而不是从一个场景到视图控制器
  • 您需要从场景的 viewController 调用 segue,而不是从根 viewController 调用。

标签: ios swift sprite-kit segue


【解决方案1】:

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

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

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

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

scene.viewController = self

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

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

【讨论】:

  • 这行得通。那么 rootViewController 是故事板中的初始视图控制器吗?当我将 rootViewController 变量打印到控制台时,它显示为我的 Menu VC。
  • 根视图控制器是您在应用程序委托中定义的视图控制器,或者在情节提要中使用根视图控制器。每个 iOS 应用程序都需要一个根 VC。当您开始游戏时,您的菜单/根 VC 对您的 SKScene VC 执行 segue。要返回,需要调用 SKScene VC 上的一个 segue,而不是根 VC 上的一个。
  • 嘿,伙计们,我实现了这个并且它可以工作,除非你从场景到视图控制器的第 4 次之后,游戏会非常滞后。我认为这是因为scene.viewController = self 在您将场景的视图控制器留给另一个视图控制器时并没有被解除 - 我将如何解除它以防止这种情况发生?
  • 是的,您每次进入菜单时都会在堆栈中添加卡片,您不会返回。为了真正删除视图控制器,只需将上面的最后一步更改为: self.viewController?.dismiss(animated: true, completion: nil)
【解决方案2】:

如何从 Scene 切换到 ViewController

Swift 3 - 与 SpriteKit / UIKit 配合使用

您可以使用 NSNotification

示例:

1.) 在情节提要中创建一个 segue 并将标识符命名为“segue”

2.) 在您要从中进行切换的 ViewController 中创建一个函数。

func goToDifferentView() {

    self.performSegue(withIdentifier: "segue", sender: self)

}

3.) 在您的 ViewController 的 ViewDidLoad() 中,您正在创建观察者。

NotificationCenter.default.addObserver(self, selector: #selector(goToDifferentView), name: "segue" as NSNotification.Name, object: nil)

4.) 在您要转场的 ViewController 或场景中,在您希望触发转场的任何位置添加 Post 方法。

NotificationCenter.default.post(name: "segue" as NSNotification.Name, object: nil)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多