Насколько я могу судить, иногда действительно необходимо создать подкласс UINavigationBar, чтобы провести нестандартный рестайлинг. Иногда можно избежать этого, используя категории , но не всегда.
В настоящее время, насколько мне известно, единственный способ установить пользовательский 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
я разархивирую этот шаблон и устанавливаю для себя результат разархивирования:
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 {
[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
- но пока это работает.