How to programmatically subclass a UINavigationBar for a UINavigationController?

I use the custom drawRect function to draw on the UINavigationBar in my application in iOS4, it does not use images, but only CoreGraphics.

Since you cannot implement drawRect in the UINavigationBar category on iOS5, Apple offers a subclass of UINavigationBar .

How can I replace a UINavigationBar my subclass with a UINavigationController (so it will be compatible with iOS4 and iOS5) if the navigationBar property is read-only?

 @property(nonatomic, readonly) UINavigationBar *navigationBar 

I do not use XIB at all in my application, so adding a UINavigationBar to the NIB and changing the class via InterfaceBuilder is not an option.

+23
ios iphone cocoa-touch uinavigationcontroller uinavigationbar
Jul 12 '11 at 22:57
source share
6 answers

As in iOS6, now it's pretty simple to do this without swizzling or messing with other classes using the UINavigationControllers initWithNavigationBarClass:toolbarClass:

 - (id)initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass; 

From the docs:

Initializes and returns a newly created navigation controller that uses your custom subclasses.

Answer updated for iOS6.

+40
Oct 06 2018-11-11T00:
source share

In iOS 6, they added a new method to the UINavigationController , which is also available in iOS 5:

 - (id)initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass; 

Now you can simply pass your own class when instantiating the navigation controller.

+81
Sep 25 '12 at 21:24
source share

The only supported way to do this in iOS 4 is to use the interface builder method. You do not need to use IB to do anything other than dialing a subclass of UINavigationBar (you can still make your entire presentation programmatically configured).

+5
Jul 13 '11 at 19:17
source share
 - (id)initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass; 

I ran into one problem with the above method. There is an initWithRootViewController method to initialize the UINavigationController. But, if I use "initWithNavigationBarClass" to run the UINavigationController, then I cannot set the "rootViewController" for the UINavigationController.

This link Modifying the UINavigationController rootViewController helped me add the rootViewController after initializing the UINavigationController using "initWithNavigationBarClass". Basically, the trick is to subclass UINavigationController. Although I have not tested it in IB yet, but it works fine in code.

+1
Nov 27 '12 at 19:48
source share

There were problems with answers 2-4 in iOS 4 (from AnswerBot answer) and I need a way to download the UINavigationController software (although the NIB method worked) ... So, I did this:

An empty XIB file is created (do not set the owner of the file), add a UINavigationController (specify its own UINavigationController class), change the UINavigationBar to your own class (here it is CustomNavigationBar), then create the following custom class header (CustomNavigationController.h in this case):

 #import <UIKit/UIKit.h> @interface CustomNavigationController : UINavigationController + (CustomNavigationController *)navigationController; + (CustomNavigationController *)navigationControllerWithRootViewController:(UIViewController *)rootViewController; @end 

and custom implementation (CustomNavigationController.mm)

 #import "CustomNavigationController.h" @interface CustomNavigationController () @end @implementation CustomNavigationController + (CustomNavigationController *)navigationController { NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomNavigationController" owner:self options:nil]; CustomNavigationController *controller = (CustomNavigationController *)[nib objectAtIndex:0]; return controller; } + (CustomNavigationController *)navigationControllerWithRootViewController:(UIViewController *)rootViewController { CustomNavigationController *controller = [CustomNavigationController navigationController]; [controller setViewControllers:[NSArray arrayWithObject:rootViewController]]; return controller; } - (id)init { self = [super init]; [self autorelease]; // We are ditching the one they allocated. Need to load from NIB. return [[CustomNavigationController navigationController] retain]; // Over-retain, this should be alloced } - (id)initWithRootViewController:(UIViewController *)rootViewController { self = [super init]; [self autorelease]; return [[CustomNavigationController navigationControllerWithRootViewController:rootViewController] retain]; } @end 

Then you can simply run this class instead of the UINavigationController and you will have a custom navigation bar. If you want to do this in xib, change the UINavigationController and UINavigationBar class inside your XIB.

0
Mar 22 2018-12-12T00:
source share

Kind of a correction to the above answers for those who still want to use initWithRootViewController . Subclass UINavigationController , and then:

 - (id) initWithRootViewController:(UIViewController *)rootViewController { self = [super initWithNavigationBarClass:[CustomNavigationBar class] toolbarClass:nil]; if (self) { self.viewControllers = [NSArray arrayWithObjects:rootViewController, nil]; } return self; } 
0
Feb 17 '14 at 7:06
source share



All Articles