Dismiss more than one view controller simultaneously

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?

  • ScrollView created in storyboard initialized with frame 0,0,0,0
  • focusing a text field in swift
  • Error when build project in new Xcode 8.0 beta
  • Fetch Facebook Mutual friends between me and another User
  • How to add subview inside UIAlertView for iOS 7?
  • How to tell if an iOS application has been newly installed or updated?
  • 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()
        }
    
    }
    

    4 Solutions Collect From Internet About “Dismiss more than one view controller simultaneously”

    @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)
    

    You can dismiss WinVC’s presenting controller (GameViewController) in the completion block:

    let presentingViewController = self.presentingViewController
    self.dismissViewControllerAnimated(false, completion: {
      presentingViewController!.dismissViewControllerAnimated(true, completion: {})
    })
    

    Alternatively, you could reach out to the root view controller and call dismissViewControllerAnimated, which will dismiss both modal viewcontrollers in a single animation:

    self.presentingViewController!.presentingViewController!.dismissViewControllerAnimated(true, completion: {})
    

    You should be able to call:

    self.presentingViewController.dismissViewControllerAnimated(true, completion: {});
    

    (You may need to add ? or ! somewhere – I’m not a swift developer)

    There’s special unwind segue intended to roll back view stack to certain view controller. Please see my answer here: how to dismiss 2 view controller in swift ios?