据我所知,有时确实需要继承 UINavigationBar 来进行一些非标准的重新设计。有时可以通过使用categories 来避免这样做,但并非总是如此。
目前,据我所知,在 UIViewController 中设置自定义 UINavigationBar 的唯一方法是通过 IB(即通过存档)- 可能不应该那样,但现在,我们必须忍受它。
这通常很好,但有时使用 IB 并不可行。
所以,我看到了三个选项:
- 子类 UINavigationBar 并将其全部连接到 IB 中,然后每次我想要一个 UINavigationController 时都要加载 nib,
- 在类别中使用method replacement 来更改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,其中包含所有设置的导航栏和工具栏,以及自定义导航栏类。我不需要做任何有点讨厌的方法替换,当我真的只是想以编程方式工作时,我也不必为 nib 乱七八糟。
我希望在 UINavigationController 中看到 +layerClass 的等价物 - +navigationBarClass - 但现在,这可行。