Question

I have simple application with only one main view, which has 'Settings' button, and settings are tree-grouped, so I wand to present them in navigation controller. And I don't want navigationController in main view, because I don't want navigation bar there.

That's why I don't instantiate navigationController in application: didFinishLaunchingWithOptions:. And when I check self.navigationController in 'Settings' button handler, it returns nil.

So I wrote this: (I use ARC)

    - (void)doSettings
    {
        NSLog(@"%@", self.navigationController); // prints nothing

        SettingsViewController *settingsViewController = [SettingsViewController alloc] initWithStyle:UITableViewStyleGrouped];

        UINavigationController *navigationController = [[UINavigationController alloc] init];
        [self.view.window setRootViewController:navigationController];
        [navigationController pushViewController:settingsViewController animated:YES];
    }

This works, although it pushes settingsViewController without animation (don't know why).

Is this generally the correct way to do - to change rootViewController in the middle of running app?

And if yes - than when I'm done with Settings, I probably need to set rootViewController back to current viewController, as it was before I tapped 'Settings'?

Was it helpful?

Solution

I think you want to create a navigation controller that you will present modally; the following will do:

SettingsViewController* settingsViewController = [[SettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; 
UINavigationController *navigationController = [[UINavigationController alloc] init]; 
[navigationController pushViewController:settingsViewController animated:YES];
[self presentViewController: navigationController animated: YES completion:nil];

where self here is the view controller you want to trigger the modal view controller from.

since you present modally the navigation controller you can dismiss it within the code source of your settingsViewController by accessing its navigation controller:

[self.navigationController dismissViewControllerAnimated:YES completion: nil];

To answer your question setting the rootViewController is not the correct way. Present the new vc modally through the presentViewController method.

OTHER TIPS

A better way is to build the navigation vc and present it over your main vc (not replace your main vc).

- (void)doSettings
{
    NSLog(@"%@", self.navigationController); // prints nothing

    SettingsViewController *settingsViewController = [SettingsViewController alloc] initWithStyle:UITableViewStyleGrouped];
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController: settingsViewController];
    [self presentViewController: navigationController animated:YES completion:^{}];
}

Your main vc might realize (maybe as a delegate) that the settings flow is complete. It can then dismiss the presented navigation controller with:

- (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion

Alternatively, the setting flow could dismiss itself...

// somewhere in the settings vc or a vc it pushes, when we decide settings are done
self.navigationController dismissViewControllerAnimated:YES completion:^{}];

Have navigation in main view and have below line (which will hide navigation bar)

[[self navigationController] setNavigationBarHidden:YES animated:YES];

(I would say have this in viewWillAppear and viewDidLoad both, BUT in viewWillAppear is MUST).

Now in second view, to show navigation bar

[[self navigationController] setNavigationBarHidden:NO animated:YES];

Hope this will solve your problem...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top