Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Skip/Add a View Controller in Navigation Stack

I have three View Controllers embedded in Navigation Controller. I want to go from VC1 to VC3 so that in VC3 the Navigation Item's back button would direct the user to VC2 instead of VC1. I think this should be done either by adding the VC2 to the Navigation Stack between VC1 and VC3 when VC3 is created or by skipping the second View Controller.

I tried this:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if let identifier = segue.identifier {
        switch identifier {
        case "JumpToThirdVCSegue":
            if let secondvc = segue.destinationViewController as? SecondViewController {
                secondvc.performSegueWithIdentifier("ThirdVCSegue", sender: self)
            }
        default: break
        }
    }
}

but I couldn't get it working. Perhaps performing a segue isn't possible when the View Controller isn't open yet?

What is the best way to skip a View Controller / add a View Controller in the middle of Navigation Stack? I hope this helps you to understand what I'm trying to do:

like image 481
Aleksi Sjöberg Avatar asked Aug 21 '15 08:08

Aleksi Sjöberg


People also ask

How do I add a view controller to my navigation controller?

Step 1: Embed root view controller inside a navigation controller. In your storyboard, select the initial view controller in your hierarchy. With this view controller selected, choose the menu item Editor -> Embed In -> Navigation Controller .

How do I navigate from one view controller to another in storyboard?

So moving from one controller to another firstly we have to create an instance of storyboards and create the reference of view controller from that we can push or present view controller over the current view controller and that same code we have to write in each class where we are moving from one controller to the ...

How do I segue to another view controller?

Well, in addition to that, Ctrl+dragging also helps set up segues. So, Ctrl+Drag from the “Go to Other View Controller” button, to somewhere in the second View Controller. It can be anywhere in the main box of the second view controller. When you release, it will show you a box like the one below.

How do I embed a view controller?

Open Main. storyboard and select the view controller of the scene that is already present. Open the Identity Inspector on the right and set Class to MasterViewController in the Custom Class section. With the view controller selected, choose Embed In > Navigation Controller from the Editor menu.


3 Answers

Something like this should work:

    self.navigationController?.pushViewController(viewController2, animated: true)
    self.navigationController?.pushViewController(viewController3, animated: true)

EDIT:

If you want to push the second view controller without being noticed by the user you need to add it to the navigation controller after the third view controller is pushed. This can be done by implementing UINavigationControllerDelegate. You can store your second view controller in a variable and insert it to the navigation controllers hierarchy in delegate method. Your main view controller will look like following:

class MyViewController: UIViewController, UINavigationControllerDelegate {

    var viewControllerToInsertBelow : UIViewController?

    override func viewDidLoad() {
        super.viewDidLoad()
        self.navigationController?.delegate = self
    }

    func pushTwoViewControllers() {
        if let viewController2 = self.storyboard?.instantiateViewControllerWithIdentifier("id1"),
            let viewController3 = self.storyboard?.instantiateViewControllerWithIdentifier("id2") { //change this to your identifiers
                self.viewControllerToInsertBelow = viewController2
                self.navigationController?.pushViewController(viewController3, animated: true)
        }
    }

    //MARK: - UINavigationControllerDelegate
    func navigationController(navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
        if let vc = viewControllerToInsertBelow {
            viewControllerToInsertBelow = nil
            let index = navigationController.viewControllers.indexOf(viewController)!
            navigationController.viewControllers.insert(vc, atIndex: index)
        }
    }

}
like image 57
Adam Avatar answered Oct 12 '22 11:10

Adam


if var navstack = navigationController?.viewControllers{
                    navstack.append(contentsOf: [vc1,vc2])
                    navigationController?.setViewControllers(navstack, animated: true)
                }

Works well

like image 23
user1632355 Avatar answered Oct 12 '22 13:10

user1632355


Edit: using swift and segues, this should work:

override func performSegueWithIdentifier(identifier: String?, sender: AnyObject?) {
    super.performSegueWithIdentifier(identifier, sender: sender);

    if identifier == "JumpToThirdVCSegue" {
        // now the vc3 was already pushed on the navigationStack
        var navStackArray : [AnyObject]! = self.navigationController!.viewControllers
        // insert vc2 at second last position
        navStackArray.insert(viewController2, atIndex: navStackArray.count - 2)
        // update navigationController viewControllers
        self.navigationController!.setViewControllers(navStackArray, animated:false)
    }
}

So you override the performSegueWithIdentifier in the VC1 in order to change the navigation stack when the segue to VC3 has actually been performed (and is not only in preparation). This assumes, that you want to handle this special navigation logic in VC1.

like image 37
MarkHim Avatar answered Oct 12 '22 13:10

MarkHim