applemavs applemavs - 1 month ago 7
iOS Question

Stop Navigation Controller from affecting other View Controllers

I have an app that uses a Navigation Controller with three View Controllers for step-by-step user setup. So the first View would be Step 1, second Step 2, and etc. And all this would be embedded in a Navigation Controller so the user would be able to go back and forth. However, once this setup is done and the user presses the 'Done' button, the app programmatically moves to another section of the storyboard which is supposed to be separate from the initial setup. I programmatically segue to this section with the following code:

let vc : AnyObject! = self.storyboard!.instantiateViewControllerWithIdentifier("welcomeViewController")
self.showViewController(vc as! UIViewController, sender: vc)


where "welcomeViewController" is the identifier for the post-setup ViewController. However, once this happens, the Navigation Controller Bar still appears on the top and you can still navigate back into the setup menu, which is not at all what I want. Here's what I mean:

enter image description here

The user shouldn't be able to access the initial setup after already setting up. My storyboard looks like this:

enter image description here

The left four boxes are for setup. The right three boxes is the 'Main Menu' I want to create.

As you can see, there's no arrow between the last setup Controller and the Tab Bar Controller because I performed that segue programmatically (as shown above). How do I get the Navigation Controller to stop affecting the rest of my View Controllers?

Answer

This happens because a segue under the hood makes use of the current UINavigationController, so it doesn't matter if you perform the segue programmatically or in the storyboards directly.

There a number of ways how to approach this. A very easy way to achieve it is to simply hide the back button in your WelcomeViewController using self.navigationItem.hidesBackButton = YES;.

However, this doesn't really solve your problem if you really want a separation between these view controllers and want to get rid of the UINavigationController that was responsible for your setup process. What I would actually recommend for that kind of situation is to use two different storyboards, one for your initial setup and one for the main part. Then you switch your UIWindow's rootViewController to a view controller from the other storyboard programmatically. This can be done in few lines of code and helps to separate your concerns and keep a better visual overview on your app's flow.

Let me know in the comments if you need further explanation :)

Switching storyboards can be achieved using the following code:

UIStoryboard *main = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
UIViewController *welcomeViewController = [main instantiateViewControllerWithIdentifier:@"WelcomeViewController"];
UIWindow *mainApplicationWindow = [[[UIApplication sharedApplication] delegate] window];
mainApplicationWindow.rootViewController = welcomeViewController;

But if you want to instantiate the whole UITabBarController you use in you r main interface, you'll have to give it an ID (e.g. MainTabBarController) in storyboards so that you can instantiate it using instantiateViewControllerWithIdentifier:. So then, instead of instantiating your WelcomeViewController, you'll go:

UIStoryboard *main = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
UITabBarController *mainTabBarController = [main instantiateViewControllerWithIdentifier:@"MainTabBarController"];
UIWindow *mainApplicationWindow = [[[UIApplication sharedApplication] delegate] window];
mainApplicationWindow.rootViewController = mainTabBarController;
Comments