简体   繁体   English

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

[英]Unable to segue from Spritekit SKScene to another UIViewController, XCODE8/Swift

I'm completely stuck at trying to perform a segue out of the 5th and final scene of my SpriteKit game to another View Controller in the project(not the GameViewController, nor the root view controller). 我完全坚持尝试从我的SpriteKit游戏的第5个和最后一个场景中执行一个segue到项目中的另一个View Controller(不是GameViewController,也不是根视图控制器)。

I tried running self.view!.window!.rootViewController!.performSegueWithIdentifier("finalSegue", sender: self), from my finalScene, but it literally does nothing (the line gets triggered, it reads the right ViewController - i check by "print(self.view!.window!.rootViewController!)" console prints "segue read" as I instructed it, right after the segue command, as a check, the segue identifier is correct, but nothing happens). 我尝试运行self.view!.window!.rootViewController!.performSegueWithIdentifier(“finalSegue”,sender:self),来自我的finalScene,但它确实什么都没做(行被触发,它读取正确的ViewController - 我检查“打印(self.view!.window!.rootViewController!)“控制台打印”segue读取“按照我的指示,在segue命令之后,作为检查,segue标识符是正确的,但没有任何反应)。

Have tried calling a method that performs the segue from the GameViewController ( the view controller from which I am launching the view of the 5 SKScenes), I get "unexpectedly found nil while unwrapping an optional value". 尝试调用一个从GameViewController(我正在启动5个SKScenes视图的视图控制器)执行segue的方法,我得到“在展开可选值时意外发现nil”。 Tried performing the segue from the final scene ("finalScene.swift"), same error. 尝试从最终场景(“finalScene.swift”)执行segue,同样的错误。

Have tried everything and all relevant solutions in other questions in the forum, as well as all combinations of nil/self/viewController in the "sender:" field of the performSegue method, to no avail. 已经在论坛中的其他问题中尝试了所有相关解决方案,以及performSegue方法的“sender:”字段中的nil / self / viewController的所有组合,但无济于事。 Here is the code that I am trying to make work which gives "unexpectedly found nil while unwrapping an optional value", pointing at the viewController var, but giving uncomprehensible debugging when loaded both on the device and on the simulator. 这是我正在努力做的工作的代码,它给出了“在展开可选值时意外发现nil”,指向viewController var,但在设备和模拟器上加载时给出了难以理解的调试。 It seems "nil" passes into the viewController var I am declaring, instead of the original GameViewController? 似乎“nil”传入我声明的viewController var,而不是原来的GameViewController?

All my segue identifiers are correct in Storyboard, everything checked multiple times...What am I doing wrong? 我在Storyboard中的所有segue标识符都是正确的,所有内容都经过多次检查...我做错了什么? Should I do something different, given its the 5th SKScene and not the 1st (as in other solutions)? 我应该做一些不同的事情,鉴于它的第5个SKScene而不是第1个(与其他解决方案一样)? The segue into the SKScenes by segueing into the GameViewController from another UIViewController works fine - its the exit out of them that does not work. 通过从另一个UIViewController中进入GameViewController而进入SKScenes的工作正常 - 它们退出它们不起作用。 Many thanks for any help, completely stuck here! 非常感谢任何帮助,完全卡在这里!

Here is my relevant code: 这是我的相关代码:

In my GameViewController (UIViewController that launches my 5 consecutive 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 
        }
    }
    }

Im my 5th scene, finalScene: 我是我的第五个场景,finalScene:

class finalScene: SKScene {

    var viewController: GameViewController!

override func touchesBegan(_ touches: Set<UITouch>, 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)            

}
        }
    }

Just for anyone who might come across this, I solved it by using notification center. 对于任何可能遇到此问题的人,我都是通过使用通知中心解决的。 Ie added a notification observer on the parent view controller of the game scenes (which calls a function that performs the segue), and at the end point in the game where I wanted to do the segue, I posted to that notification, and it works great. 即在游戏场景的父视图控制器上添加了一个通知观察者(调用执行segue的函数),并且在我想要做segue的游戏的终点,我发布了该通知,它的工作原理大。

adding observer in ViewDidLoad of UIViewController: 在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
    }

And then calling it from within the game SKScene: 然后从游戏SKScene中调用它:

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

You are calling the segue on the root viewController. 您正在根viewController上调用segue。 I think that is the problem. 我认为这就是问题所在。 You need to call the segue on the scene's viewController instead (where I am assuming you have created the segue, hence it is not being found on the root viewController). 你需要在场景的viewController上调用segue(我假设你创建了segue,因此它没有在根viewController上找到)。

Now the problem is that an SKScene does not have direct access to it's viewController, but just the view in which it is contained. 现在问题是SKScene没有直接访问它的viewController,而只是它包含它的视图。 You need to create a pointer to it manually. 您需要手动创建指向它的指针。 This can be done by creating a property for the SKScene: 这可以通过为SKScene创建属性来完成:

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

Then, in the viewController class, just before skView.presentScene(scene) 然后,在viewController类中,就在skView.presentScene(scene)之前

scene.viewController = self

Now, you can access the viewController directly. 现在,您可以直接访问viewController。 Simply call the segue on this viewController: 只需在此viewController上调用segue:

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

Found this method to work just as well. 发现这种方法同样适用。 But I do prefer the method mentioned above since it's fewer lines. 但我确实更喜欢上面提到的方法,因为它的线数较少。 I do wonder which is better for performance... 我不知道哪个更适合表现......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM