如何以编程方式为UINavigationController创建UINavigationBar的子类?

时间:2011-07-12 22:57:59

标签: iphone ios cocoa-touch uinavigationcontroller uinavigationbar

我正在使用自定义drawRect函数在iOS4中的应用程序上绘制UINavigationBar,它不使用图像,只使用CoreGraphics。

由于您无法在iOS5中的UINavigationBar类别中实现drawRect,因此Apple建议继承UINavigationBar

UINavigationBar属性为只读时,如何用UINavigationController中的navigationBar代替我的子类(因此它将与iOS4和iOS5兼容)?

@property(nonatomic, readonly) UINavigationBar *navigationBar

我根本不在我的应用程序中使用XIB,因此向NIB添加UINavigationBar并通过InterfaceBuilder更改类不是一种选择。

6 个答案:

答案 0 :(得分:81)

在iOS 6中,他们为UINavigationController添加了一种新方法,该方法在iOS 5中也可以缩进:

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

现在,您可以在实例化导航控制器时传递自定义类。

答案 1 :(得分:41)

从iOS6开始,现在使用UINavigationControllers方法initWithNavigationBarClass:toolbarClass:

轻松完成其他类的操作非常简单
- (id)initWithNavigationBarClass:(Class)navigationBarClass 
                    toolbarClass:(Class)toolbarClass;

来自文档:

  

初始化并返回一个新创建的导航控制器   使用您的自定义栏子类。

为iOS6更新了答案。

答案 2 :(得分:5)

在iOS 4中唯一支持的方法是使用Interface Builder方法。除了设置UINavigationBar子类之外,您不必使用IB来执行任何操作(您仍然可以通过编程方式设置所有视图)。

答案 3 :(得分:1)

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

我遇到了上述方法的一个问题。 有一个“initWithRootViewController”方法来初始化UINavigationController。 但是,如果我使用“initWithNavigationBarClass”来初始化UINavigationController,那么我无法为UINavigationController设置“rootViewController”。

这个链接Changing a UINavigationController's rootViewController帮助我在用“initWithNavigationBarClass”初始化UINavigationController之后添加了一个rootViewController。基本上,诀窍是子类UINavigationController。虽然我还没有在IB中测试它,但它在代码中运行良好。

答案 4 :(得分:1)

对那些仍然想要使用initWithRootViewController的人进行上述答案的修改。子类UINavigationController然后:

- (id) initWithRootViewController:(UIViewController *)rootViewController
{
    self = [super initWithNavigationBarClass:[CustomNavigationBar class] toolbarClass:nil];
    if (self)
    {
        self.viewControllers = [NSArray arrayWithObjects:rootViewController, nil];
    }

    return self;
}

答案 5 :(得分:0)

iOS 4中的答案2-4问题(来自AnswerBot的答案),并且需要一种以编程方式加载UINavigationController的方法(尽管NIB方法有效)......所以我这样做了:

创建一个空白XIB文件(不要设置文件所有者),添加一个UINavigationController(给它自定义UINavigationController的类),将UINavigationBar更改为自定义类(这里是CustomNavigationBar),然后创建以下自定义类头(在这种情况下CustomNavigationController.h):

#import <UIKit/UIKit.h>

@interface CustomNavigationController : UINavigationController
+ (CustomNavigationController *)navigationController;
+ (CustomNavigationController *)navigationControllerWithRootViewController:(UIViewController *)rootViewController;
@end

和自定义实现(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

然后你可以初始化那个类而不是UINavigationController,你将拥有自定义导航栏。如果你想在xib中执行它,请在XIB中更改UINavigationController和UINavigationBar的类。