3

In my app I have three table view controllers and then potentially many UIViewControllers each of which has to lead back to the first table view controller if the user presses back at any point. I don't want the user to have to back through potentially hundreds of pages. This is what I amusing to determine if the user pressed the back button and it works the message is printed

override func viewWillDisappear(_ animated: Bool) {
    if !movingForward {
        print("moving back")
        let startvc = self.storyboard!.instantiateViewController(withIdentifier: "FirstTableViewController")
        _ = self.navigationController!.popToViewController(startvc, animated: true)
    }
}

I have searched and none of the solutions have worked so far.

Filipe
  • 137
  • 3
  • 12

3 Answers3

14

popToViewController not work in a way you are trying you are passing a complete new reference of FirstTableViewController instead of the one that is in the navigation stack. So you need to loop through the navigationController?.viewControllers and find the FirstTableViewController and then call popToViewController with that instance of FirstTableViewController.

for vc in (self.navigationController?.viewControllers ?? []) {
    if vc is FirstTableViewController {
        _ = self.navigationController?.popToViewController(vc, animated: true)
        break
    }
}

If you want to move to First Screen then you probably looking for popToRootViewController instead of popToViewController.

_ = self.navigationController?.popToRootViewController(animated: true)
Nirav D
  • 71,513
  • 12
  • 161
  • 183
  • Ohh, didnt know that. It works! however there is a small delay. It first loads the previous view and then jumps to the one I want it to. Any way to fix this? – Filipe Apr 21 '17 at 09:51
  • @Filipe Set animated to `false` because you are calling it inside ``viewWillDisappear` – Nirav D Apr 21 '17 at 09:59
  • @Filipe Your previous is showing because you have put this code inside `viewWillDisappear` instead of that you need to set the custom back bar button as leftBarButtonItem and with action of that method add this code – Nirav D Apr 21 '17 at 10:26
  • @NiravD How can i pass the value b/w view controllers when using popToViewController??? – ArgaPK Jan 24 '18 at 14:02
  • @ArgaPK The best way to handle this situation is to use protocol/delegate with shared instance of some Utill class. – Nirav D Jan 25 '18 at 04:34
1

Try this :

let allViewController: [UIViewController] = self.navigationController!.viewControllers as [UIViewController];

                        for aviewcontroller : UIViewController in allViewController
                        {
                            if aviewcontroller .isKindOfClass(YourDestinationViewControllerName)// change with your class
                            {
                             self.navigationController?.popToViewController(aviewcontroller, animated: true)
                            }
                        }
KKRocks
  • 8,222
  • 1
  • 18
  • 84
  • Works as well, but I'm running into the same issue as with the other solution, which is that the previous view is still showing before it goes to the desired one. Any fix? – Filipe Apr 21 '17 at 09:58
  • which previous view ? – KKRocks Apr 21 '17 at 10:06
-1

If you are in a callback, particularly an async network callback, you may not be on the main thread. If that's you're problem, the solution is:

DispatchQueue.main.async {
    self.navigationController?.popToViewController(startvc, animated: true)
}

The system call viewWillDisappear() is always called on the main thread.

bshirley
  • 8,217
  • 1
  • 37
  • 43