Eric H
Eric H

Reputation: 1353

Clearing Navigation Stack in Swift

I'm currently designing an application that has a funnel flow and a dashboard flow. I'd like the funnel flow to be cleared from memory on completion:

So if it goes 1) if new user start funnel -> 2) funnel screens 1-5 -> 3) funnel complete screen

I'd like to transition to dashboard screen which is not yet on the stack (it's not my head controller in this case). How can I clear the 6 screens above from memory when I transition to dashboard - basically setting a new navigation root and clearing the rest? An unwind segue doesn't appear to be able to set a new root destination.

Upvotes: 10

Views: 20296

Answers (3)

Julius B.
Julius B.

Reputation: 191

If you only want to clear the navigation stack, and push a new view on top of it, there is an even simpler solution.

Let's suppose you already (programmatically) assigned a navigation controller, e.g. in a viewDidLoad() function, like:

let navController = UINavigationController( rootViewController: YourRootController )
view.addSubview( navController.view )
addChildViewController( navController )

navController.didMoveToParentViewController( self )

YourRootController acts as the stacks's root (the bottom of the stack).

To push other controllers on top of the stack (your funnel controllers), simply use navController.pushViewController( yourControllerInstance!, animated: false ).

If you want to clear the stack after completion of the funnel, just call:

navController.popToRootViewControllerAnimated( false )

This function removes all views (besides the root controller) from your stack.

Upvotes: 13

Eric H
Eric H

Reputation: 1353

So I ended up having to do it programmatically by popping back to the first controller and then replacing from the funnel head to the dashboard head:

func bookingCompleteAcknowledged(){
    //remove the popup controller
    dismissViewControllerAnimated(true, completion: nil)
    //remove current controller
    dismissViewControllerAnimated(true, completion: nil)

    if let topController = UIApplication.sharedApplication().keyWindow?.rootViewController {

        if let navcontroller = topController.childViewControllers[0] as? UINavigationController{
          navcontroller.popToRootViewControllerAnimated(false)

            if let funnelcontroller = navcontroller.childViewControllers[0] as? FunnelController {
                funnelcontroller.removeFromParentViewController();
                funnelcontroller.view.removeFromSuperview();

                let revealController = self.storyboard?.instantiateViewControllerWithIdentifier("DashboardController") as! SWRevealViewController

                navcontroller.addChildViewController(revealController)
                navcontroller.view.addSubview(revealController.view)
            }
        }
    }

}

Upvotes: 3

Aurast
Aurast

Reputation: 3688

I believe you can do this by simply assigning a new array (with just the dashboard view, in your case) to the UINavigationController's viewControllers property.

Why do you want to use the same navigation controller instead of making a new one? Generally, instead of trying to change the root of a navigation controller, I would recommend just creating a new navigation controller.

Upvotes: 0

Related Questions