Как я могу удалить ViewController из моего GameScene.swift?

ВОПРОС: Как я могу удалить ViewController из моего GameScene.swift?


СИТУАЦИЯ: у меня есть 2 VC в моей игре SpriteKit, например:

ViewController.swift ----Нажмите Play-----> GameViewController

Когда игрок проигрывает, я хочу закрыть GameViewController, чтобы игрок мог снова нажать кнопку воспроизведения. Я проверяю потерю игрока в моем GameScene.swift и хотел бы закрыть GameVC оттуда.


Примечание: безуспешно гуглил.


ЧТО Я ПРОБОВАЛ:

1) Создание экземпляра gameVC в моем GameScene.swift и его удаление следующим образом:

let gameVC = GameViewController()
gameVC.dismissViewController(false,completion: nil)

2) Делаем:

self.view.window!.rootViewController?.dismissViewControllerAnimated(false, completion: nil)

Они не работают по понятным причинам ^^


person Coder1000    schedule 21.05.2016    source источник
comment
1) не сработает: вам нужно использовать существующий экземпляр, а не новый. 2) будет работать только в том случае, если self.view.window!.rootViewController? является вашим экземпляром GameViewController, но похоже, что это, вероятно, ViewController.   -  person Aaron Brager    schedule 21.05.2016
comment
@AaronBrager Да, я знаю :) Вот почему я поместил это в раздел «Что я пробовал». Я просто не понимаю, как захватить существующий экземпляр:/   -  person Coder1000    schedule 21.05.2016
comment
Вам нужно либо передать GameScene ссылку на контроллер представления, чтобы он мог отклонить его, либо использовать шаблон делегата для обратной связи с управляющим объектом, что VC должен быть отклонен/отклонен сам   -  person Aaron Brager    schedule 21.05.2016
comment
@AaronBrager Поместите это в ответ, чтобы я мог принять его (если это сработает): D   -  person Coder1000    schedule 21.05.2016


Ответы (2)


Вы не хотите «захватывать» существующий экземпляр: https://pragprog.com/articles/tell-dont-ask

Вам нужно либо передать GameScene ссылку на контроллер представления, чтобы он мог его закрыть, либо использовать шаблон делегата для обратного сообщения управляющему объекту о том, что VC должен быть закрыт/закрыт сам.

Простой пример… вы можете добавить свойство GameViewController к GameScene, а затем закрыть VC в нужное время:

class GameScene: SKScene {
    var gameVC: GameViewController?

    func gameDidEnd() {
        gameVC?.dismissViewControllerAnimated(true) {
            // if desired, do any cleanup after the VC is dismissed
        }
    }
}

Затем просто установите это свойство при создании объекта GameScene в первую очередь:

if let gameScene = GameScene(fileNamed: "MyScene") {
    gameScene.gameVC = someGameVC
}

Этот простой подход тесно свяжет GameScene и GameViewController, что немного усложнит задачу, если вы когда-нибудь захотите использовать один из этих объектов без другого. Но для этого простого варианта использования это может быть хорошо.

person Aaron Brager    schedule 21.05.2016
comment
Спасибо за ответ, но SO против ответов только по ссылкам, потому что они могут стать недействительными. Не могли бы вы добавить фрагмент кода, чтобы я мог принять ваш ответ и проголосовать за него? :) - person Coder1000; 21.05.2016
comment
Конечно, я рад. Одну секунду - person Aaron Brager; 21.05.2016
comment
У меня есть утечка памяти после того, как я попробовал это:/ - person Coder1000; 21.05.2016
comment
Можете ли вы уточнить? - person Aaron Brager; 21.05.2016
comment
Каждый раз, когда я проигрываю (закрываю GameVC, поэтому возвращаюсь в mainVC, где есть кнопка воспроизведения) и играю снова, FPS падает. - person Coder1000; 21.05.2016
comment
Похоже, у вас может быть сильный эталонный цикл. Вы можете попробовать weak var gameVC, если да. - person Aaron Brager; 21.05.2016
comment
Вот оно! Спасибо ! (Может быть, вы также отредактируете свой ответ с помощью weak?) - person Coder1000; 21.05.2016
comment
Не думайте, что мне следует редактировать свой ответ - weak необходимо только из-за строгого цикла ссылок, но это не требуется ни в вашем вопросе, ни в моем ответе. - person Aaron Brager; 21.05.2016
comment
Хорошо, интересно, где я создал этот сильный цикл ссылок :/ Я всегда стараюсь избегать их, но на этот раз, похоже, он ускользнул от меня ›:) - person Coder1000; 21.05.2016
comment
Может быть, ваш контроллер представления имеет сильную ссылку на сцену? - person Aaron Brager; 21.05.2016
comment
Вы можете рассмотреть возможность использования одного контроллера представления и подхода с несколькими сценами. stackoverflow.com/a/35409586 - person Whirlwind; 31.05.2016

Я следил за некоторыми вашими обсуждениями. Я хочу добавить немного кода, потому что обычно я предпочитаю работать с одним ViewController или двумя и многими SKScene и SKNode, но в этом случае может быть полезно иметь ссылку currentViewController:

class MyModelScene: SKScene {
   let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
   var currentViewController : MyModelViewController! = MyModelViewController() 
 // MyModelViewController is a customized UIViewController

   override func didMoveToView(view: SKView) {
      super.didMoveToView(view)
      print("---")
      print("∙ \(NSStringFromClass(self.dynamicType))")
      print("---")
   }
}

class Level1Scene: MyModelScene {
    ...
}

В UIViewController:

class PreloadViewController: MyModelViewController {
     override func viewDidLoad() {
        super.viewDidLoad()

        if let scene = Level1Scene(fileNamed:"Level1Scene") {
            // Configure the view.
            let skView = self.view as! SKView
            skView.showsFPS = true
            skView.showsPhysics = true
            skView.showsNodeCount = true

            skView.ignoresSiblingOrder = true

            /* Set the scale mode to scale to fit the window */
            scene.scaleMode = .ResizeFill 
            scene.currentViewController = self
            skView.presentScene(scene)
        }
    }
}

С помощью этого кода у вас всегда есть ссылка на currentViewController в вашем SKScene, и вы можете проверить, является ли это правильным viewController, который вы хотите отклонить или нет.

person Alessandro Ornano    schedule 30.05.2016
comment
Вам не нужно NSStringFromClass; все типы Swift могут быть преобразованы в строки. - person Aaron Brager; 31.05.2016
comment
Красавчик, спасибо, я даже не заметил, потому что исходит из моего старого кода +1 - person Alessandro Ornano; 31.05.2016