I'm making a game using SpriteKit. I have 3 viewControllers: selecting level vc, game vc, and win vc. After the game is over, I want to show the win vc, then if I press OK button on the win vc, I want to dismiss the win vc AND the game vc (pop two view controllers out of the stack). But I don't know how to do it because if I call
self.dismissViewControllerAnimated(true, completion: {})
the win vc (top of the stack) is dismissed, so I don't know where to call it again to dismiss the game vc. Is there any way I can fix this without using navigation controller?
This is the 1st VC: (Please pay attention to my comments below starting with "//")
class SelectLevelViewController: UIViewController { // I implemented a UIButton on its storyboard, and its segue shows GameViewController override func viewDidLoad() { super.viewDidLoad() } }
This is the 2nd VC:
class GameViewController: UIViewController, UIPopoverPresentationControllerDelegate { var scene: GameScene! var stage: Stage! var startTime = NSTimeInterval() var timer = NSTimer() var seconds: Double = 0 var timeStopped = false var score = 0 @IBOutlet weak var targetLabel: UILabel! @IBOutlet var displayTimeLabel: UILabel! @IBOutlet weak var scoreLabel: UILabel! @IBOutlet weak var gameOverPanel: UIImageView! @IBOutlet weak var shuffleButton: UIButton! @IBOutlet weak var msNum: UILabel! var mapNum = Int() var stageNum = Int() var tapGestureRecognizer: UITapGestureRecognizer! override func viewDidLoad() { super.viewDidLoad() let skView = view as! SKView skView.multipleTouchEnabled = false scene = GameScene(size: skView.bounds.size) scene.scaleMode = .AspectFill msNum.text = "\(mapNum) - \(stageNum)" stage = Stage(filename: "Map_0_Stage_1") scene.stage = stage scene.addTiles() scene.swipeHandler = handleSwipe gameOverPanel.hidden = true shuffleButton.hidden = true skView.presentScene(scene) Sound.backgroundMusic.play() beginGame() } func beginGame() { displayTimeLabel.text = String(format: "%ld", stage.maximumTime) score = 0 updateLabels() stage.resetComboMultiplier() scene.animateBeginGame() { self.shuffleButton.hidden = false } shuffle() startTiming() } func showWin() { gameOverPanel.hidden = false scene.userInteractionEnabled = false shuffleButton.hidden = true scene.animateGameOver() { self.tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "hideWin") self.view.addGestureRecognizer(self.tapGestureRecognizer) } } func hideWin() { view.removeGestureRecognizer(tapGestureRecognizer) tapGestureRecognizer = nil gameOverPanel.hidden = true scene.userInteractionEnabled = true self.performSegueWithIdentifier("win", sender: self) // this segue shows WinVC but idk where to dismiss this GameVC after WinVC gets dismissed... } func shuffle() {...} func startTiming() {...} }
And this is the 3rd VC:
class WinVC: UIViewController { @IBOutlet weak var awardResult: UILabel! @IBAction func dismissVC(sender: UIButton) { self.dismissViewControllerAnimated(true, completion: {}) // dismissing WinVC here when this button is clicked } override func viewDidLoad() { super.viewDidLoad() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }
Use unwind segue instead of using RootViewController. Using unwind you can go back to any ViewController. DismissViewController always send the controller out from NavigationController.
When it comes time to dismiss a presented view controller, the preferred approach is to let the presenting view controller dismiss it. In other words, whenever possible, the same view controller that presented the view controller should also take responsibility for dismissing it.
@Ken Toh's comment was what worked for me in this situation -- call dismiss from the view controller that you want to show after everything else is dismissed.
If you have a "stack" of 3 presented view controllers A
, B
and C
, where C
is on top, then calling A.dismiss(animated: true, completion: nil)
will dismiss B and C simultaneously.
If you don't have a reference to the root of the stack, you could chain a couple of accesses to presentingViewController
to get to it. Something like this:
self.presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With