Насколько я могу судить, иногда действительно необходимо создать подкласс UINavigationBar, чтобы провести нестандартный рестайлинг. Иногда этого можно избежать, используя категории, но не всегда.
В настоящее время, насколько мне известно, only способ установить пользовательский UINavigationBar в UIViewController через 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
, но пока это работает.
person
Michael Tyson
schedule
20.06.2010