私が知る限り、非標準のスタイル変更を行うために UINavigationBar をサブクラス化することが実際に必要になる場合があります。カテゴリを使用することで回避できる場合もありますが、常にそうとは限りません。
現在、私の知る限り、UIViewController 内でカスタム UINavigationBar を設定する唯一の方法は IB を使用すること (つまり、アーカイブを使用すること) です。おそらくそのようにするべきではありませんが、今のところは、それと一緒に暮らす必要があります。
多くの場合、これで問題ありませんが、IB の使用が現実的でない場合もあります。
そのため、次の 3 つのオプションがありました。
- UINavigationBar をサブクラス化し、IB にすべて接続してから、UINavigationController が必要になるたびに nib をロードすることをいじくりまわします。
- サブクラス化ではなく、カテゴリ内でメソッド置換を使用して UINavigationBar の動作を変更する、または
- UINavigationBar をサブクラス化し、UINavigationController のアーカイブ/アーカイブ解除を少しいじります。
UINavigationController をプログラムで作成する必要があったため、この場合、オプション 1 は実行不可能でした (または、少なくとも煩わしすぎました)。2 は少し危険であり、最後の手段であると考えているため、オプション 3 を選択しました。
私のアプローチは、UINavigationController の「テンプレート」アーカイブを作成し、それを解凍してinitWithRootViewController
.
方法は次のとおりです。
IB では、UINavigationBar に適切なクラス セットを使用して UINavigationController を作成しました。
次に、既存のコントローラを取得し、.xml を使用してそのアーカイブ コピーを保存しました+[NSKeyedArchiver archiveRootObject:toFile:]
。シミュレーターのアプリデリゲート内でこれを行いました。
次に、「xxd」ユーティリティを -i フラグとともに使用して、保存したファイルから C コードを生成し、アーカイブ バージョンをサブクラスに組み込みました ( xxd -i path/to/file
)。
その中でinitWithRootViewController
、そのテンプレートを解凍し、解凍の結果を self に設定します。
// This is the data from [NSKeyedArchiver archivedDataWithRootObject:controller], where
// controller is a CTNavigationController with navigation bar class set to CTNavigationBar,
// from IB. This c code was created using 'xxd -i'
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 {
// Replace with unarchived view controller, necessary for the custom navigation bar
[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
が、今のところ、これは機能します。