Как создать подкласс UINavigationBar для UINavigationController программно? - PullRequest
23 голосов
/ 13 июля 2011

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

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

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

@property(nonatomic, readonly) UINavigationBar *navigationBar

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

Ответы [ 6 ]

81 голосов
/ 26 сентября 2012

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

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

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

41 голосов
/ 06 октября 2011

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

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

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

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

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

5 голосов
/ 13 июля 2011

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

1 голос
/ 17 февраля 2014

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

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

    return self;
}
1 голос
/ 27 ноября 2012
- (id)initWithNavigationBarClass:(Class)navigationBarClass toolbarClass:(Class)toolbarClass;

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

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

0 голосов
/ 22 марта 2012

У меня были проблемы с ответами 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.

...