カスタムdrawRect関数を使用して、iOS4のアプリケーション全体でUINavigationBar
を描画しています。画像は使用せず、CoreGraphicsのみを使用しています。
IOS5ではUINavigationBar
カテゴリにdrawRectを実装できないため、AppleはUINavigationBar
をサブクラス化することを提案しています。
UINavigationBar
プロパティが読み取り専用の場合、UINavigationController
をnavigationBar
のサブクラスに置き換える(iOS4およびiOS5と互換性がある)にはどうすればよいですか?
@property(nonatomic, readonly) UINavigationBar *navigationBar
私はアプリケーションでXIBをまったく使用していないため、NIBにUINavigationBar
を追加し、InterfaceBuilderを介してクラスを変更することはできません。
IOS6以降、これはUINavigationControllers
メソッドinitWithNavigationBarClass:toolbarClass:
を使用することで、他のクラスをスウィズルしたり混乱させたりすることなく、非常に簡単に実行できるようになりました。
- (id)initWithNavigationBarClass:(Class)navigationBarClass
toolbarClass:(Class)toolbarClass;
ドキュメントから:
カスタムバーサブクラスを使用する、新しく作成されたナビゲーションコントローラーを初期化して返します。
IOS6用に更新された回答。
IOS 6では、iOS5でも撤回的に利用できる新しいメソッドをUINavigationController
に追加しました。
- (id)initWithNavigationBarClass:(Class)navigationBarClass
toolbarClass:(Class)toolbarClass;
これで、ナビゲーションコントローラーがインスタンス化されたときに、カスタムクラスを渡すことができます。
IOS 4でこれを行うためにサポートされている唯一の方法は、InterfaceBuilderメソッドを使用することです。 UINavigationBarサブクラスを設定する以外にIBを使用する必要はありません(プログラムで設定されたすべてのビューを実行できます)。
まだ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;
上記の方法で1つの問題に直面しました。 UINavigationControllerを初期化するための「initWithRootViewController」メソッドがあります。ただし、「initWithNavigationBarClass」を使用してUINavigationControllerを初期化すると、UINavigationControllerに「rootViewController」を設定する方法がありません。
このリンク INavigationControllerのrootViewControllerを変更する は、UINavigationControllerが「initWithNavigationBarClass」で初期化された後にrootViewControllerを追加するのに役立ちました。基本的に、トリックはUINavigationControllerをサブクラス化することです。まだIBでテストしていませんが、コードでは正常に機能しています。
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のクラスを変更します。