Xcodeで iOS アプリの新規プロジェクトを作成する際、Navigation-based ApplicationやView-based Applicationといったテンプレートを選択することができますが、その両方の機能性を持たせたいということがあると思います。というか、さっきそういう境遇に陥って困ったので、メモです。
今回は、アプリのトップ画面は View-based Application だけれども、そこからメニューを選んだときには NavigationController のスタックに積んで、Navigation Bar 付きのページに遷移していくというもの。うむ、説明が難しい。平たく言うと、トップ画面は Navigation Bar がなくて、2階層目の画面は Navigation Bar があってトップに戻れる感じです。
さっそく作ります。ここでは、Sampleというアプリを考えます。
まず、View-based Application テンプレートを使ってプロジェクトを作成します。これに NavigationController の機能を追加していきます。
はじめに SampleAppDelegate.h を開いて、UINavigationController を追加します。1行追加するだけ。
@interface SampleAppDelegate : NSObject <UIApplicationDelegate> { UIWindow *window; UINavigationController *navigationController; SampleViewController *viewController; }
次に SampleAppDelegate.m を開いて、application:didFinishLaunchingWithOptions: と dealloc を以下のように修正します。NavigationController の rootViewController に、デフォルトの UIViewController をセットして、その view を window のサブビューに追加して表示させるようにしているのがポイントでしょうか。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { navigationController = [[UINavigationController alloc] initWithRootViewController:viewController]; // Add the view controller's view to the window and display. [window addSubview:navigationController.view]; [window makeKeyAndVisible];
return YES; }
- (void)dealloc { [viewController release]; [navigationController release]; [window release]; [super dealloc]; }
続いて、トップ画面では NavigationBar を隠し、2階層目以降は表示するようにします。ここでは next: が、2階層目を開く処理として、ボタンか何かに紐付けた IBAction 的なメソッドということにします。
SampleViewController.m を開いて、以下のような感じにします。
#import "SampleViewController.h" #import "NextViewController.h" @implementation SampleViewController - (void)viewWillAppear:(BOOL)animated { self.navigationController.navigationBarHidden = YES; } - (void)hoge:(id)sender { NextViewController *next = [[NextViewController alloc] init]; [self.navigationController pushViewController:next animated:YES]; [next release]; self.navigationController.navigationBarHidden = NO; }
// 以下略
ここでのポイントは、 navigationBarHidden に BOOL オブジェクトをセットするタイミングです。pushViewController:animated: する前に NavigationBar を表示しようとすると、画面遷移前ににょきっと NavigationBar が現れてくるので、あんまり心地良くありません。いろいろ試してみていただければと思いますが、コードを書く位置で、目に見える違いがあるのが GUI 開発の面白いところですね。
これで目的達成です。おつかれさまでした。大したことないですが、そのうち github にでも上げときます。