How to add an UINavigationController to an existing UIViewController programmatically

27,562

This is not how UINavigationControllers work. You need to set A as the rootViewController of your UINavigationController. UINavigationController is a container for other view controllers.

For example, in your AppDelegate you might do something like this:

UIViewController *A = [[UIViewController alloc] init];    
UINavigationController *navVC = [[UINavigationController alloc] initWithRootViewController:A];
UIViewController *X = [[UIViewController alloc] init];
UIViewController *Y = [[UIViewController alloc] init];
UIViewController *Z = [[UIViewController alloc] init];
UITabBarController *tabVC = [[UITabBarController alloc] init];
tabVC.viewControllers = @[X, Y, Z, navVC];
self.window.rootViewController = tabVC;

And in A

- (IBAction)pressButton:(id)sender
{
    [self.navigationController pushViewController:B animated:YES];
}
Share:
27,562
photosynthesis
Author by

photosynthesis

Updated on March 02, 2020

Comments

  • photosynthesis
    photosynthesis about 4 years

    I am newbie to iOS programming, and this problem may seem stupid to someone, I am sorry. I have a problem here is that I have an existing UIViewController (A), and another UIViewController (B), I want to add an UINavigationController to A such that when I press a button on A, I will be lead to B. I tried the following approach, but it does not solve the problem:

    in AppDelegate:

    @synthesize navigationController;
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        // Override point for customization after application launch.
    
        self.tabbarController = [[UITabBarController alloc] init];
        UIViewController *viewController_1 = [[WUSTLViewController_1 alloc] init];
        UIViewController *viewController_2 = [[WUSTLViewController_2 alloc] init];
    
        UIViewController *viewController_3 = [[WUSTLViewController_3 alloc] init];
        navigationController = [[UINavigationController alloc] initWithRootViewController: viewController_3];
    
        self.tabbarController.viewControllers = [NSArray arrayWithObjects:viewController_1, viewController_2, navigationController, nil];
        self.window.rootViewController = self.tabbarController;
    
        self.window.backgroundColor = [UIColor whiteColor];
        [self.window makeKeyAndVisible];
        return YES;
    }
    

    In WUSTLViewController_3.h (A):

    #import <UIKit/UIKit.h>
    #import "WUSTLViewController_4.h"
    
    @interface WUSTLViewController_3 : UIViewController {
        WUSTLViewController_4 *viewController_4;
    }
    
    @property UINavigationController *navigationController;
    
    @end
    

    In WUSTLViewController_3.m (A):

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        viewController_4 = [[WUSTLViewController_4 alloc] init];
    
        UIButton *myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        myButton.frame = CGRectMake(80, 50, 150, 40);
        [myButton setTitle:@"Push" forState:UIControlStateNormal];
        [myButton addTarget:self action:@selector(pressButton:) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:myButton];
    }
    
    - (IBAction)pressButton:(id)sender
    {
        [self.navigationController pushViewController:viewController_4 animated:YES];
    }
    

    When I click the button, nothing happened.

  • photosynthesis
    photosynthesis about 10 years
    I added the following code to viewDidLoad in A: b = [[B alloc] init]; navigationController = [[UINavigationController alloc] initWithRootViewController: b]; [self presentViewController:navigationController animated:YES completion:nil]; Besides, in the push button method I did this: [self.navigationController pushViewController:b animated:YES]; But still does not work, in the first step, I tried to init the navigation with root A, in the second step I tried to use it.
  • photosynthesis
    photosynthesis about 10 years
    Like you said, I put the code which you suggested to put in the AppDelegate in the viewDidLoad in A, and keep the same with you for the code in pressButton, but it does not work, where did I go wrong, please?
  • Rob Jones
    Rob Jones about 10 years
    Then you didn't do what I suggested. A must be controlled by a UINavigationController. Wherever you're presenting A, present a UINavigation controller with A as the rootViewController instead.
  • photosynthesis
    photosynthesis about 10 years
    I followed your suggestion and modified my code again, still does not work. I didn't add this line of code "self.window.rootViewController = navVc;" because what actually in my project is A is one of the UIController controlled by a UITabViewController, thus the root controller should be the tabController. The relation is much like this: tabController --> (X, Y, Z, A --> B).
  • Rob Jones
    Rob Jones about 10 years
    Ok, so then in the place where you're adding A to the UITabBarController, you should add the code I suggested. The UINavigationController should be the view controller for one of your tabs.
  • Rob Jones
    Rob Jones about 10 years
    I edited my answer to show how to do it with a UITabBarController as your application's rootViewController.
  • Rob Jones
    Rob Jones about 10 years
    Is viewController_4 an ivar? If so, that should work.
  • photosynthesis
    photosynthesis about 10 years
    yes, viewController_4 is an instance variable in the header file of A.
  • Rob Jones
    Rob Jones about 10 years
    Remove the @property UINavigationController *navigationController; from WUSTLViewController_3.h. If you read the docs for UIViewController, you'll see there's already a navigationController property. My guess is your synthesized methods are masking UIViewController's navigationController property.
  • photosynthesis
    photosynthesis about 10 years
    OMG, it works! I believe the property defined by me somewhat block the controller to use the default one. Thank you very much!