How to programatically unwind or pop multiple viewControllers on back UIBarButton?

I have 6 viewControllers in following manner. VCA,VCB,VCC,VCD,VCE,VCF.

mainVC-->VCA-->VCB-->VCC-->VCD...VCE

mainVC-->VCA-->VCD...VCF

(-->) are connected by segues while (...) VCE and VCF are programatically pushed in navigationController.

My question is how can I pop multiple viewControllers from VCD,VCE or VCF to VCA on Back UIBarButton on navigationController

enter image description here

According to this StackOverFlow questions Link and Link :-

Tried this code but it didn't work.

override func viewDidLoad {
    super.viewDidLoad()
    self.navigationItem.hidesBackButton = true
    let newBackButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.plain, target: self, action: #selector(YourViewController.back(sender:)))
    self.navigationItem.leftBarButtonItem = newBackButton
}

func back(sender: UIBarButtonItem) {
   let presentingViewController = self.presentingViewController
   self.dismissViewControllerAnimated(false, completion: {
   presentingViewController!.dismissViewControllerAnimated(true, completion: {}) //.dismiss(animated:true, completion:{})
   })
}

3 answers

  • answered 2018-01-16 13:33 AntiVIRUZ

    Delete all view controllers from navigationController?.viewControllers between your current view controller (it will be the last) and view controller, then do navigationController?.popViewController(animated: true)

  • answered 2018-01-16 13:45 DonMag

    If you know that VCA was pushed onto mainVC, then your navigation controller stack is [mainVC, VCA, VCB, ..., VCF] or [mainVC, VCA, VCD, ..., VCF], so you want to pop back to the VC at item 1 of the stack:

    func back(sender: UIBarButtonItem) {
    
            if let vc = navigationController?.viewControllers[1] {
                _ = navigationController?.popToViewController(vc, animated: true)
            }
    
    }
    

    If what you really want to do is pop back to the root VC of the navigation controller, you can simply:

    func back(sender: UIBarButtonItem) {
    
            _ = navigationController?.popToRootViewController(animated: true)
    
    }
    

  • answered 2018-01-16 14:07 Milan NosáΔΎ

    Try this simple extension:

    extension UIViewController {
    
        func dismissToTop() {
            topPresentingViewController?.dismiss(animated: true, completion: nil)
        }
    
        var topPresentingViewController: UIViewController? {
            var presenting: UIViewController? = self.presentingViewController
            while let presPres = presenting?.presentingViewController {
                presenting = presPres
            }
            return presenting
        }
    }
    

    And then use following code:

    override func viewDidLoad {
        super.viewDidLoad()
        self.navigationItem.hidesBackButton = true
        let newBackButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.plain, target: self, action: #selector(YourViewController.back(sender:)))
        self.navigationItem.leftBarButtonItem = newBackButton
    }
    
    func back(sender: UIBarButtonItem) {
        self.dismissToTop()
    }