据我所知,有时确实有必要将 UINavigationBar 子类化,以进行一些非标准的重新设计。有时可以通过使用categories来避免这样做,但并非总是如此。
目前,据我所知,在 UIViewController 中设置自定义 UINavigationBar 的唯一方法是通过 IB(即通过存档)——它可能不应该这样,但现在,我们必须接受它。
这通常很好,但有时使用 IB 并不可行。
所以,我看到了三个选项:
- 子类 UINavigationBar 并将其全部连接到 IB 中,然后每次我想要一个 UINavigationController 时都想加载笔尖,
- 在类别中使用方法替换来改变 UINavigationBar 的行为,而不是子类化,或者
- 子类 UINavigationBar 并在归档/取消归档 UINavigationController 方面做一些处理。
在这种情况下,选项 1 对我来说是不可行的(或者至少太烦人了),因为我需要以编程方式创建 UINavigationController,在我看来,2 有点危险,而且更像是最后的选择,所以我选择了选项 3。
我的方法是创建 UINavigationController 的“模板”存档,然后取消存档,将其返回为initWithRootViewController
.
就是这样:
在 IB 中,我创建了一个 UINavigationController,并为 UINavigationBar 设置了适当的类。
然后,我使用现有的控制器,并使用+[NSKeyedArchiver archiveRootObject:toFile:]
. 我只是在模拟器中的应用程序委托中执行此操作。
然后我使用带有 -i 标志的 'xxd' 实用程序,从保存的文件生成 c 代码,将存档版本嵌入到我的子类 ( xxd -i path/to/file
) 中。
在initWithRootViewController
我取消归档该模板,并将 self 设置为取消归档的结果:
// This is the data from [NSKeyedArchiver archivedDataWithRootObject:controller], where
// controller is a CTNavigationController with navigation bar class set to CTNavigationBar,
// from IB. This c code was created using 'xxd -i'
static unsigned char archived_controller[] = {
0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30, 0xd4, 0x01, 0x02, 0x03,
...
};
static unsigned int archived_controller_len = 682;
...
- (id)initWithRootViewController:(UIViewController *)rootViewController {
// Replace with unarchived view controller, necessary for the custom navigation bar
[self release];
self = (CTNavigationController*)[NSKeyedUnarchiver unarchiveObjectWithData:[NSData dataWithBytes:archived_controller length:archived_controller_len]];
[self setViewControllers:[NSArray arrayWithObject:rootViewController]];
return [self retain];
}
然后,我可以获取我的 UIViewController 子类的一个新实例,它设置了自定义导航栏:
UIViewController *modalViewController = [[[CTNavigationController alloc] initWithRootViewController:myTableViewController] autorelease];
[self.navigationController presentModalViewController:modalViewController animated:YES];
这给了我一个带有导航栏和工具栏的模态 UITableViewController,并设置了自定义导航栏类。我不需要做任何有点讨厌的方法替换,当我真的只想以编程方式工作时,我也不必为 nibs 烦恼。
我想+layerClass
在 UINavigationController中看到等价物+navigationBarClass
- 但现在,这可行。