web-dev-qa-db-ja.com

プログラムでUINavigationControllerのUINavigationBarをサブクラス化する方法は?

カスタムdrawRect関数を使用して、iOS4のアプリケーション全体でUINavigationBarを描画しています。画像は使用せず、CoreGraphicsのみを使用しています。

IOS5ではUINavigationBarカテゴリにdrawRectを実装できないため、AppleはUINavigationBarをサブクラス化することを提案しています。

UINavigationBarプロパティが読み取り専用の場合、UINavigationControllernavigationBarのサブクラスに置き換える(iOS4およびiOS5と互換性がある)にはどうすればよいですか?

@property(nonatomic, readonly) UINavigationBar *navigationBar

私はアプリケーションでXIBをまったく使用していないため、NIBにUINavigationBarを追加し、InterfaceBuilderを介してクラスを変更することはできません。

23
romaonthego

IOS6以降、これはUINavigationControllersメソッドinitWithNavigationBarClass:toolbarClass:を使用することで、他のクラスをスウィズルしたり混乱させたりすることなく、非常に簡単に実行できるようになりました。

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

ドキュメントから:

カスタムバーサブクラスを使用する、新しく作成されたナビゲーションコントローラーを初期化して返します。

IOS6用に更新された回答。

42
memmons

IOS 6では、iOS5でも撤回的に利用できる新しいメソッドをUINavigationControllerに追加しました。

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

これで、ナビゲーションコントローラーがインスタンス化されたときに、カスタムクラスを渡すことができます。

81
Javier Soto

IOS 4でこれを行うためにサポートされている唯一の方法は、InterfaceBuilderメソッドを使用することです。 UINavigationBarサブクラスを設定する以外にIBを使用する必要はありません(プログラムで設定されたすべてのビューを実行できます)。

5
Ross Kimes

まだinitWithRootViewControllerを使用したい人のために、上記の回答に対する一種の修正。サブクラスUINavigationControllerそして:

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

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

上記の方法で1つの問題に直面しました。 UINavigationControllerを初期化するための「initWithRootViewController」メソッドがあります。ただし、「initWithNavigationBarClass」を使用してUINavigationControllerを初期化すると、UINavigationControllerに「rootViewController」を設定する方法がありません。

このリンク INavigationControllerのrootViewControllerを変更する は、UINavigationControllerが「initWithNavigationBarClass」で初期化された後にrootViewControllerを追加するのに役立ちました。基本的に、トリックはUINavigationControllerをサブクラス化することです。まだIBでテストしていませんが、コードでは正常に機能しています。

1
sudip

IOS 4の回答2〜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でそれを実行したい場合は、XIB内のUINavigationControllerとUINavigationBarのクラスを変更します。

0
BadPirate