Peter G.
Peter G.

Reputation: 8054

Controlling UINavigationItem content from within UINavigationController

I am trying to programmatically set the contents of the UINavigationItem for the entire application from a central location (the View Controllers can then add their own buttons) within the UINavigationController, e.g.:

viewDidLoad method of the UINavigationController:

UINavigationItem *item = [[UINavigationItem alloc] initWithTitle:@"Login"];
[self.navigationBar pushNavigationItem:item animated:NO];
self.navigationItem.topItem.leftBarButtonItems = [[NSArray alloc] initWithObjects: filterBtn, editBtn, nil];
self.navigationItem.rightBarButtonItems = [[NSArray alloc] initWithObjects: userBtn, infoBtn, mapsBtn, nil];

However, when calling pushViewController from a UINavigationController, the presented UINavigationItem gets set to default, with its title equal to the name of the scene.

[self pushViewController:viewController animated:NO];

Without calling pushViewController I am able to see my custom UINavigationItem.

The problem might be:

  1. I'm using the storyboard to instantiate the view controller: UIViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier: screen];

  2. That instead of push I should be using [self presentViewController:viewController animated:NO completion:nil], however, this method hides the navigation bar completely

  3. A workaround might be to just present the UIView, but I'd rather avoid it for now.

What am I doing wrong here?

Upvotes: 1

Views: 229

Answers (1)

Bilal
Bilal

Reputation: 19156

Whenever a UIViewController is pushed navigation items (left, middle, right) are replaced.

Navigation controller will push the default items if custom items (left, middle, right) has not been set of the UIViewController.

In your case what you can do is, Implement the UINavigationControllerDelegate within the UINavigationController and implement this method navigationController(UINavigationController, willShow: UIViewController, animated: Bool) method. And you can assign default navigation items just before pushing the UIViewController. And can also check if any custom item has been set or not.

func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {

    if viewController.navigationItem.leftBarButtonItem == nil { // viewController.navigationItem.leftBarButtonItems
        // assign default item
    }

    if viewController.navigationItem.rightBarButtonItem == nil { // viewController.navigationItem.rightBarButtonItems
        // assign default item
    }

    if viewController.navigationItem.titleView == nil {
        // assign default item
    }
}

You can also have a look at the official documentation here. See section The Left Item and own-words.

Option 2

Create a BaseViewController and inherit all your view with BaseViewController. And then in BaseViewController you can set all the default navigation items.

class BaseViewController : UIViewController {
    override func viewDidLoad() {
        self.navigationItem.leftBarButtonItems = [[NSArray alloc] initWithObjects: filterBtn, editBtn, nil];
        self.navigationItem.rightBarButtonItems = [[NSArray alloc] initWithObjects: userBtn, infoBtn, mapsBtn, nil];
    }
}

Upvotes: 1

Related Questions