Как создать подкласс UINavigationBar для UINavigationController программно?

Я использую пользовательскую функцию drawRect, чтобы рисовать на UINavigationBar в моем приложении в iOS4 оно не использует изображения, только CoreGraphics.

Поскольку вы не можете реализовать drawRect в UINavigationBar Apple в категории iOS5 предлагает подкласс UINavigationBar,

Как можно заменить UINavigationBar с моим подклассом в UINavigationController (так что он будет совместим с iOS4 и iOS5), когда navigationBar свойство только для чтения?

@property(nonatomic, readonly) UINavigationBar *navigationBar

Я вообще не использую XIB в своем приложении, поэтому добавляю UINavigationBar к NIB и изменение класса через InterfaceBuilder не вариант.

6 ответов

Решение

Начиная с iOS6, теперь это довольно просто сделать без использования других классов с помощью UINavigationControllers метод initWithNavigationBarClass:toolbarClass:

- (id)initWithNavigationBarClass:(Class)navigationBarClass 
                    toolbarClass:(Class)toolbarClass;

Из документов:

Инициализирует и возвращает вновь созданный контроллер навигации, который использует ваши пользовательские подклассы панели.

Ответ обновлен для iOS6.

В iOS 6 они добавили новый метод UINavigationController это доступно и в iOS 5:

- (id)initWithNavigationBarClass:(Class)navigationBarClass
                    toolbarClass:(Class)toolbarClass;

Теперь вы можете просто передать свой пользовательский класс при создании экземпляра контроллера навигации.

Единственный поддерживаемый способ сделать это в iOS 4 - использовать метод Interface Builder. Вам не нужно использовать IB, чтобы делать что-либо, кроме как установить подкласс UINavigationBar (вы все равно можете сделать все свои представления настроенными программно).

Вид поправки к ответам выше для тех, кто все еще хочет использовать initWithRootViewController, Подкласс UINavigationController а потом:

- (id) initWithRootViewController:(UIViewController *)rootViewController
{
    self = [super initWithNavigationBarClass:[CustomNavigationBar class] toolbarClass:nil];
    if (self)
    {
        self.viewControllers = [NSArray arrayWithObjects:rootViewController, nil];
    }

    return self;
}
- (id)initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass;

Я столкнулся с одной проблемой, описанной выше. Для инициализации UINavigationController существует метод initWithRootViewController. Но если я использую "initWithNavigationBarClass" для инициализации UINavigationController, то я не смогу установить "rootViewController" для UINavigationController.

Эта ссылка Изменение rootViewController в UINavigationController помогло мне добавить rootViewController после того, как UINavigationController инициализирован с помощью initWithNavigationBarClass. По сути, дело в том, чтобы создать подкласс UINavigationController. Хотя я еще не тестировал его в IB, но в коде он работает нормально.

У него были проблемы с ответами 2-4 в iOS 4 (из ответа AnswerBot), и нужен был способ загрузить UINavigationController программно (хотя метод NIB работал)... Итак, я сделал это:

Создайте пустой XIB-файл (не устанавливайте владельца файла), добавьте UINavigationController (предоставьте ему свой пользовательский класс UINavigationController), измените UINavigationBar на свой пользовательский класс (здесь это CustomNavigationBar), затем создайте следующий заголовок пользовательского класса (CustomNavigationController.h). в этом случае):

#import <UIKit/UIKit.h>

@interface CustomNavigationController : UINavigationController
+ (CustomNavigationController *)navigationController;
+ (CustomNavigationController *)navigationControllerWithRootViewController:(UIViewController *)rootViewController;
@end

и пользовательская реализация (CustomNavigationController.mm)

#import "CustomNavigationController.h"

@interface CustomNavigationController ()

@end

@implementation CustomNavigationController
+ (CustomNavigationController *)navigationController
{
    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomNavigationController" owner:self options:nil];
    CustomNavigationController *controller = (CustomNavigationController *)[nib objectAtIndex:0];
    return controller;
}


+ (CustomNavigationController *)navigationControllerWithRootViewController:(UIViewController *)rootViewController
{
    CustomNavigationController *controller = [CustomNavigationController navigationController];
    [controller setViewControllers:[NSArray arrayWithObject:rootViewController]];
    return controller;
}

- (id)init
{
    self = [super init];
    [self autorelease]; // We are ditching the one they allocated.  Need to load from NIB.
    return [[CustomNavigationController navigationController] retain]; // Over-retain, this should be alloced
}

- (id)initWithRootViewController:(UIViewController *)rootViewController
{
    self = [super init];
    [self autorelease];
    return [[CustomNavigationController navigationControllerWithRootViewController:rootViewController] retain];
}
@end

Тогда вы можете просто инициализировать этот класс вместо UINavigationController, и у вас будет собственная панель навигации. Если вы хотите сделать это в xib, измените класс UINavigationController и UINavigationBar внутри вашей XIB.

Другие вопросы по тегам