How to subclass UINavigationBar for a UINavigationController programmatically?

后端 未结 6 427
半阙折子戏
半阙折子戏 2020-11-29 20:00

I\'m using a custom drawRect function to draw on UINavigationBar across my application in iOS4, it doesn\'t use images, only CoreGraphics.

Since you ca

相关标签:
6条回答
  • 2020-11-29 20:20

    As of iOS6, this is now quite simple to accomplish without swizzling or messing with other classes by using UINavigationControllers method initWithNavigationBarClass:toolbarClass:

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

    From the docs:

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

    Answer updated for iOS6.

    0 讨论(0)
  • 2020-11-29 20:22
    - (id)initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass;
    

    I faced one problem with the above method. There is a "initWithRootViewController" method to initialize UINavigationController. But, if I use "initWithNavigationBarClass" to init the UINavigationController, then there is no way I could set "rootViewController" for the UINavigationController.

    This link Changing a UINavigationController's rootViewController helped me to add a rootViewController after the UINavigationController is initialized with "initWithNavigationBarClass". Basically, the trick is to subclass UINavigationController. Though I haven't tested it in IB yet, but it is working fine in code.

    0 讨论(0)
  • 2020-11-29 20:27

    In iOS 6 they added a new method to UINavigationController that is retractively available in iOS 5 as well:

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

    Now you can just pass your custom class when the navigation controller is instantiated.

    0 讨论(0)
  • 2020-11-29 20:29

    Kind of an amendment to the answers above for those that 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 讨论(0)
  • 2020-11-29 20:31

    The only supported way to do this in iOS 4 is to use the Interface Builder method. You don't have to use IB to do anything except set the UINavigationBar subclass (you can still do all of your view set up programmatically).

    0 讨论(0)
  • 2020-11-29 20:32

    Had issues with answers 2-4 in iOS 4 (from AnswerBot's answer), and needed a way to load the UINavigationController programmatically (though the NIB method worked)... So I did this:

    Created a Blank XIB file (don't set file owner), add a UINavigationController (give it your custom UINavigationController's class), change the UINavigationBar to your custom class (here it's 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 just init that class instead of a UINavigationController, and you'll have your custom navigation bar. If you want to do it in a xib, change the class of UINavigationController and UINavigationBar inside of your XIB.

    0 讨论(0)
提交回复
热议问题