【问题标题】:How to do a reference of my UIViewController in the SKScene?如何在 SKScene 中引用我的 UIViewController?
【发布时间】:2016-10-14 20:21:52
【问题描述】:

我需要将 UIViewController 作为我的 GameScene 的属性。 所以在调用 presentScene 之前,我用 UIViewController 设置了属性。

我的 UIViewController 类:

class GameViewController: UIViewController {

    var scene:GameScene!

    override func viewDidLoad() {
        super.viewDidLoad()

        if let scene = GKScene(fileNamed: "GameScene") {

            // Get the SKScene from the loaded GKScene
            if let sceneNode = scene.rootNode as! GameScene? {

                self.scene=sceneNode

                // Set the scale mode to scale to fit the window
                sceneNode.scaleMode = .aspectFill

                // Present the scene
                if let view = self.view as! SKView? {

                    sceneNode.gameViewController = self //SET THE PROPERTY
                    view.presentScene(sceneNode)

                    view.ignoresSiblingOrder = true
                    view.showsPhysics = true
                    view.showsFPS = true
                   view.showsNodeCount = true    
                }
            }
        }
    }
}

我的 GameScene 类:

class GameScene: SKScene, SKPhysicsContactDelegate {

    // MARK: Properties
    var gameViewController:GameViewController!

    override func sceneDidLoad() {

         print(self.gameViewController) // -> CRASH
         //DO SOME STUFF
    }
}

我遇到了这个崩溃:

fatal error: unexpectedly found nil while unwrapping an Optional value

编辑 1

所以我尝试使用:

override func didMove(to view: SKView) {
    super.didMove(to: view)

    self.physicsWorld.contactDelegate = self
    self.physicsBody!.categoryBitMask = ColliderType.DeviceBounds.rawValue

    //ALL MY INIT CODE
}


override func sceneDidLoad() {
    super.sceneDidLoad()
    //NOTHING HERE
}

但是物理世界不再起作用了。我的崩溃消失了,但物理世界被打破了。

在我的控制台中:

--->GameViewController - viewDidLoad()<---
--->GameScene - sceneDidLoad()<---
--->GameScene - sceneDidLoad()<---
--->GameScene - didMove(to:)<---
--->GameViewController - viewWillAppear<---
--->GameViewController - viewDidAppear<---

【问题讨论】:

  • 真正的问题是,你为什么要这样做,这是最好的方法。通过 GameScene 持有 UIViewController,您将面临 GameScecne 和 ViewController 永远不允许释放的风险

标签: ios swift uiviewcontroller sprite-kit skscene


【解决方案1】:

您忘记在此代码后添加GameViewController

// Get the SKScene from the loaded GKScene
            if let sceneNode = scene.rootNode as! GameScene? {

行:

               sceneNode.gameViewController = self

另外,在你的场景类中你应该使用:

override func didMove(to view: SKView) {

因为sceneDidLoad() 方法(现在在iOS10 中)相当于UIKit 中的viewDidLoad()但是你的场景还没有被视图呈现

【讨论】:

  • 不,该行就在 view.presentScene(sceneNode) 之前
  • 我听从了你的建议,但它发生了一些奇怪的事情,一旦我使用了 override func didMove(to view: SKView),所有的物理行为在我的场景中都不起作用......我不'不明白为什么。
  • 您是否也放入了 didMove self.physicsWorld.contactDelegate = self 和其他与您的物理世界相关的初始化?
  • 检查你是如何创建你的physicsBodies的,可能你对与场景相关的你的身体的起源或大小有一些问题。
  • 好的,我要去搜索,但是为什么只是在 didMove 中移动我的代码,我的物理就坏了?它在sceneDidLoad 中完美运行。我什么都没改,坐标系是一样的。
【解决方案2】:

sceneDidLoad 函数在您设置对 gameViewController 的引用之前被调用。您应该改用 SKScene didMoveToView 函数。

override func didMove(to view: SKView) {
    print(self.gameViewController)
}

您可以在 Xcode 中(在您的 gameScene 和 gameViewController 中)设置断点并查看事件的时间安排。顺便说一句,使用协议实现delegate pattern 比使用像这样的具体引用更好。

【讨论】:

    【解决方案3】:

    在 GameSceneViewController 上使用 ViewDid 加载:

    if let scene = SKScene(fileNamed: "GameScene") {
      currentGame = scene as! GameScene
      currentGame.gameViewController = self
     }
    

    那么你就可以同时拥有两者相互参照了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-20
      • 1970-01-01
      • 2015-01-19
      • 1970-01-01
      • 1970-01-01
      • 2013-10-26
      • 1970-01-01
      相关资源
      最近更新 更多