Using Navigation Controllers in iOS Development: A Deep Dive into Storyboards and View Controllers

Understanding Navigation Controllers in iOS Development

=====================================================

In iOS development, a Navigation Controller (UINavigationController) plays a crucial role in managing the flow of user interaction within an application. It provides a way to navigate between different view controllers and manages the back button for each view controller. In this article, we’ll explore how to use a Navigation Controller with storyboards and embed it inside another view controller.

Introduction


A Navigation Controller is a type of view controller that uses navigation rules to manage the flow of user interaction within an application. It’s typically used in conjunction with storyboards to define the layout and behavior of different view controllers. When a Navigation Controller is added to a storyboard, it automatically creates a back button for each view controller in the navigation hierarchy.

Creating a Storyboard with Multiple View Controllers


In this section, we’ll create a new project in Xcode and design a storyboard that contains two view controllers: MainViewController and SearchViewController. We’ll also embed SearchViewController inside the Navigation Controller.

Step 1: Create a New Project

Open Xcode and create a new project. Select “Single View App” as the template and choose the iOS template. Name your project, e.g., “NavigationControllerDemo”.

Step 2: Design the Storyboard

Open the Main.storyboard file in the project navigator. Drag and drop two view controllers onto the storyboard: MainViewController and SearchViewController. Select both view controllers and go to the Utilities panel.

Drag a Navigation Controller from the Object Library (bottom-left corner of the Xcode window) into the main storyboard area. This will create a new navigation controller that wraps around both view controllers.

Using the Navigation Controller with Storyboards


When we embed SearchViewController inside the Navigation Controller, it automatically creates a back button for each view controller in the navigation hierarchy. However, when we load the SearchViewController programmatically using instantiateViewControllerWithIdentifier, the Navigation Controller is not properly configured.

Why Does the Navigation Controller Become Nil?

In our example code:

UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Search" bundle: [NSBundle mainBundle]];
SearchViewController *search = (SearchViewController *)[[sb instantiateViewControllerWithIdentifier:@"SearchViewController"] visibleViewController];
[self addChildViewController:search];
[self.view addSubview:search.view];

We’re using instantiateViewControllerWithIdentifier to create an instance of the SearchViewController. However, this approach doesn’t properly configure the Navigation Controller. The instantiateViewControllerWithIdentifier method creates a new instance of the view controller without adding it to the navigation stack.

Configuring the Navigation Controller Programmatically


To fix the issue and make the Navigation Controller appear properly when loading the SearchViewController, we need to add the view controller to the navigation stack programmatically. We can do this by creating an instance of the UINavigationController and adding the view controllers to its stack.

Step 1: Create a New View Controller Class

Create a new file in the project navigator (e.g., NavigationControllerConfigurator.h) with the following code:

#import <UIKit/UIKit.h>

@interface NavigationControllerConfigurator : NSObject

- (void)configureNavigatorsForViewControllers:(NSArray<UIViewController *> *)viewControllers;

@end

Step 2: Implement the Configure Method

Create a new file in the project navigator (e.g., NavigationControllerConfigurator.m) with the following code:

#import "NavigationControllerConfigurator.h"

@implementation NavigationControllerConfigurator

- (void)configureNavigatorsForViewControllers:(NSArray<UIViewController *> *)viewControllers {
    UINavigationController *navigationController = [[UINavigationController alloc] init];
    
    for (UIViewController *viewController in viewControllers) {
        [navigationController pushViewController:viewController animated:YES];
        
        if ([viewController isKindOfClass:[SearchViewController class]]) {
            // Add the SearchViewController to the navigation stack
            [navigationController setViewControllers:@[viewController]];
            
            break;
        }
    }
    
    self.view = navigationController.view; // Set the view controller's view property
}

@end

Step 3: Use the Configure Method

Modify the MainViewController class (e.g., MainViewController.m) to use the configureNavigatorsForViewControllers method:

#import "NavigationControllerConfigurator.h"

@implementation MainViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // Create an instance of the SearchViewController
    UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Search" bundle: [NSBundle mainBundle]];
    SearchViewController *search = (SearchViewController *)[[sb instantiateViewControllerWithIdentifier:@"SearchViewController"] visibleViewController];
    
    // Configure the Navigation Controller programmatically
    NavigationControllerConfigurator *configurator = [[NavigationControllerConfigurator alloc] init];
    [configurator configureNavigatorsForViewControllers:@[self, search]];
}

@end

Conclusion


In this article, we’ve explored how to use a Navigation Controller with storyboards and embed it inside another view controller. We’ve also discussed why the Navigation Controller becomes nil when loading the SearchViewController programmatically.

By creating an instance of the UINavigationController and adding the view controllers to its stack programmatically, we can configure the Navigation Controller properly and make it appear as expected when loading the SearchViewController.

We hope this article has provided you with a deeper understanding of how to use Navigation Controllers in iOS development. If you have any further questions or need additional clarification, please don’t hesitate to ask!


Last modified on 2024-12-23