Master-Detail template で tabBarController を追加する方法
久しぶりにはまりました。Master-Detail template はよく出来ていて、手を入れる必要がある個所が分かってくれば凄く便利なんです。
でも、TabBar を追加しようとすると状況が一変してしまう。まず、TabBar の追加の仕方がわからない。さらに、storyboard に追加しても build すると error 発生で萎える。一週間ぐらい悩んで、ようやく error にならないようになりました。備忘のため手順を記しておこうと思います。
- テンプレートでは、Master-Detail App を選択します。Use CoreData のチェックを入れることを忘れないようにします。
- Main.storyboard を開きます。UISplitViewController が Storyboard Entry Point になっていますが、そのままで大丈夫です。UITabBarController を追加するため、Master の navigation controller を選択します。UISplitViewController からは 2 つの segue が設定されていますが、Master の方を選択します。
- メニューから、Editor > Embed in > Tab Bar Controller を選択します。余談ですが、UISplitViewController を選択した状態でこのメニューは選べませんので安心です。メニューを選択すると、UITabBarController が追加されます。
- splitView から detail に relationship が設定されているのでこれを削除します。削除する理由は error になるからなのですが、回避方法がわからないのでひとまず削除します。
- 試しにこの状態で build してみます。build は success となりますが、simulator ではアプリ起動直後に error になります。error の原因は色々ありますが、tabBar を追加したので、topViewController の指定が適切ではないためです(ということがようやく分かりました)。なので、適切に指定するように template の内容を変更します。
- AppDelegate.m を変更します。tabBarController を追加したので、topViewController の指定を変更します。正直、正しいのかさっぱり分かりませんが、変更箇所は以下の通り。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UITabBarController* tabBarController = [splitViewController.viewControllers lastObject];
UINavigationController *navigationController = tabBarController.viewControllers[0];
navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem;
splitViewController.delegate = self;
UINavigationController *masterNavigationController = tabBarController.viewControllers[0];
MasterViewController *controller = (MasterViewController *)masterNavigationController.topViewController;
controller.managedObjectContext = self.persistentContainer.viewContext;
return YES;
}
- 試しにここで build & run してみると、エラーになります。理由は、Master の ViewController を表示しようとした時に、tabBarController を追加したことを加味していないためです。MasterViewController.m の viewDidLoad method を変更します。変更箇所は次の通りです。
変更前
self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
変更後
self.detailViewController = (DetailViewController *)[[self.tabBarController.viewControllers lastObject] topViewController];
とりあえずこれで build & run しても error にならなくなります。storyboard の detail relation をカットしてしまったので、iPad の動作検証で問題になる可能性大ですが、error にならなくなったのは精神衛生上非常によいことで、躓くまではしばらくこのまま進めてみよう。