@hedjirog です。Interface Builder や Storyboard は必要に応じて使いたい派です。
今回は UITabBarController
で複数のタブを保持する際、タブごとに Storyboard を分割する方法 を紹介します。
※ UITabBarController
で複数のタブを保持する際に、 必ず Storyboard を分割することを推奨するものではありません。 状況に応じて Storyboard の分割を検討してください。
ソースコードは GitHub からダウンロードできます。
手順
4つのタブ (Home, Connect, Discover, Me) を持つアプリケーションの開発を想定し、タブごとに Storyboard を分割することを考えます。
アプリケーションのルートの View Controller はコードから生成し、各タブの View Controller は UITabBarController
の初期化時に分割した Storyboard から生成します。
以下、手順の説明です。
1. 複数の Storyboard の生成
まずは4つの Storyboard を作成します。
ここでは Home
, Connect
, Discover
, Me
という4つの Storyboardを作成してみます。
2. UITabBarItem
の配置
それぞれの Storyboard の Initial View Controller で、UITabBarItem
を配置します。
ここでは Storyboard の Initial View Controller を Navigation Controller とし、そこに UITabBarItem
を配置してみます。
3. UIStoryboard
のカテゴリーによる拡張(必要に応じて)
分割した Storyboard をコードで扱いやすいようにカテゴリーによる UIStoryboard
クラスの拡張をしましょう。これは必須ではありません。好みや必要に応じて実装してください。
ここでは MSDExtensions
という UIStoryboard
のカテゴリーを定義してみます。
#import <UIKit/UIKit.h>
@interface UIStoryboard (MSDExtensions)
+ (instancetype)msd_homeStoryboard;
+ (instancetype)msd_connectStoryboard;
+ (instancetype)msd_discoverStoryboard;
+ (instancetype)msd_meStoryboard;
@end
#import "UIStoryboard+MSDExtensions.h"
NSString * const kHomeName = @"Home";
NSString * const kConnectName = @"Connect";
NSString * const kDiscoverName = @"Discover";
NSString * const kMeName = @"Me";
@implementation UIStoryboard (MSDExtensions)
+ (instancetype)msd_homeStoryboard
{
return [self msd_storyboardWithName:kHomeName];
}
+ (instancetype)msd_connectStoryboard
{
return [self msd_storyboardWithName:kConnectName];
}
+ (instancetype)msd_discoverStoryboard
{
return [self msd_storyboardWithName:kDiscoverName];
}
+ (instancetype)msd_meStoryboard
{
return [self msd_storyboardWithName:kMeName];
}
+ (instancetype)msd_storyboardWithName:(NSString *)name
{
return [self storyboardWithName:name bundle:nil];
}
@end
4. アプリケーション特有の UITabBarController
のサブクラスの定義
UITabBarController
を継承したクラスを定義して、アプリケーション特有の処理を定義しやすくします。
ここでは MSDTabBarController
というサブクラスを定義してみます。
#import <UIKit/UIKit.h>
@interface MSDTabBarController : UITabBarController
@end
5. ルートの View Controller の生成
App Delegate の application:didFinishLaunchingWithOptions:
メソッドでルートの View Controller を設定します。
Window の rootViewController
プロパティに対して、先ほど定義した MSDTabBarController
クラスのインスタンスをセットしましょう。
#import "MSDAppDelegate.h"
#import "MSDTabBarController.h"
@implementation MSDAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.rootViewController = [[MSDTabBarController alloc] init];
[self.window makeKeyAndVisible];
return YES;
}
@end
6. 各タブの View Controller の生成
MSDTabBarController
の初期化処理時に、各タブに保持される View Controller を Storyboard から生成します。
ここでは viewDidLoad
メソッドが呼ばれるタイミングで、viewControllers
プロパティの配列を適切に変更するようにしてみます。
#import "MSDTabBarController.h"
#import "UIStoryboard+MSDExtensions.h"
@implementation MSDTabBarController
- (void)viewDidLoad
{
[super viewDidLoad];
[self setUpViewControllers];
}
- (void)setUpViewControllers
{
self.viewControllers = @[[[UIStoryboard msd_homeStoryboard] instantiateInitialViewController],
[[UIStoryboard msd_connectStoryboard] instantiateInitialViewController],
[[UIStoryboard msd_discoverStoryboard] instantiateInitialViewController],
[[UIStoryboard msd_meStoryboard] instantiateInitialViewController]
];
}
@end
まとめ
UITabBarController
で複数のタブを扱う場合に、タブごとに Storyboard を分割する方法を紹介しました。
複数の Storyboard を扱う方法は、すでに Developers.IO の記事 でも紹介されています。
該当記事ではメインの画面遷移と共通の画面遷移のために Storyboard を作成する方法であるのに対し、ここでは メインの画面遷移のために Storyboard は作成せず、(タブごとの)独立した複数の Storyboard を作成してコードから呼び出す方法 であるという点で異なります。
UITabBarController
を利用しつつ Storyboard を分割する際は、両者を比較し、開発しているアプリケーションにより相応しい方法を選択してください。