据我所知,有时确实有必要对UINavigationBar进行子类化,以进行一些非标准的重新样式化。有时可以通过使用category来避免这样做,但并非总是如此。
目前,据我所知,在UIViewController中设置自定义UINavigationBar 的唯一方法是通过IB(即通过存档)-可能不应该这样,但是到目前为止,我们必须忍受它。
这通常很好,但是有时使用IB并不是切实可行的。
因此,我看到了三个选择:
- 子类化UINavigationBar并将其全部连接到IB中,然后每当我想要一个UINavigationController时就装满笔尖,
- 在类别中使用方法替换来更改UINavigationBar的行为,而不是子类化,或者
- 子类化UINavigationBar,然后对UINavigationController进行存档/取消存档。
在这种情况下,选项1对我来说是不可行的(或至少太烦人了),因为我需要以编程方式创建UINavigationController,所以2有点危险,我认为它是最后一种选择,所以我选择了选项3。
我的方法是为UINavigationController创建一个“模板”档案,然后将其取消存档,然后将其返回initWithRootViewController
。
这是如何做:
在IB中,我创建了一个UINavigationController,并为UINavigationBar设置了适当的类。
然后,我拿走了现有的控制器,并使用保存了它的存档副本+[NSKeyedArchiver archiveRootObject:toFile:]
。我只是在模拟器的应用程序委托中完成的。
然后,我将'xxd'实用程序与-i标志一起使用,从保存的文件生成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,其中所有导航栏和工具栏都已设置,并且自定义导航栏类就位。我不需要做任何令人讨厌的方法替换,并且当我真的只想以编程方式工作时,我不必为笔尖而烦恼。
我想看到+layerClass
UINavigationController中的等效项+navigationBarClass
--但现在可以了。