如何以编程方式为 UINavigationController 子类化 UINavigationBar?

发布于 2024-11-24 02:40:02 字数 540 浏览 1 评论 0原文

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

由于您无法在 iOS5 中的 UINavigationBar 类别中实现 drawRect,Apple 建议对 UINavigationBar 进行子类化。

navigationBar 属性时,如何用我在 UINavigationController 中的子类替换 UINavigationBar (这样它将与 iOS4 和 iOS5 兼容)是只读的吗?

@property(nonatomic, readonly) UINavigationBar *navigationBar

我根本没有在应用程序中使用 XIB,因此无法将 UINavigationBar 添加到 NIB 并通过 InterfaceBuilder 更改类。

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 can't implement drawRect in UINavigationBar category in iOS5, Apple is suggesting to subclass UINavigationBar.

How is it possible to replace the UINavigationBar with my subclass in UINavigationController (so it'll be compatible with iOS4 and iOS5) when the navigationBar property is read only?

@property(nonatomic, readonly) UINavigationBar *navigationBar

I'm not using XIBs in my application at all, so adding a UINavigationBar to a NIB and changing the class via InterfaceBuilder is not an option.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

怀中猫帐中妖 2024-12-01 02:40:03

对于那些仍然想使用 initWithRootViewController 的人来说,这是对上面答案的修改。子类 UINavigationController 然后:

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

    return self;
}

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;
}
浮生未歇 2024-12-01 02:40:03

在 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 类。

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.

只是我以为 2024-12-01 02:40:02

在 iOS 6 中,他们向 UINavigationController 添加了一个新方法,该方法在 iOS 5 中也可伸缩使用:

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

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

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.

笑饮青盏花 2024-12-01 02:40:02

开始,通过使用 UINavigationControllers 方法 initWithNavigationBarClass:toolbarClass: 可以非常简单地完成此任务,而无需调整或与其他类混淆。

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

从iOS6

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

针对 iOS6 更新了答案。

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.

娇柔作态 2024-12-01 02:40:02

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

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).

兲鉂ぱ嘚淚 2024-12-01 02:40:02
- (id)initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass;

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

此链接 更改UINavigationController 的 rootViewController 帮助我在使用“initWithNavigationBarClass”初始化 UINavigationController 后添加 rootViewController。基本上,技巧是子类化 UINavigationController。虽然我还没有在 IB 中测试它,但它在代码中运行良好。

- (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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文