UITabBarで特定のタブをタッチしたときにモーダルでビューを表示する方法

※Interface Builderは使っていません

UITabBarは基本的にはタブを切り替えるUIですが、ボタンのように使うこともあります。
(Foursquareのチェックインボタンなど)

少々強引ですが、特定のタブをタッチしたときにモーダルでビューを表示する方法を紹介します。

以下、すべてAppDelegate.[h|m]のお話です。

プロパティを追加します。

// interface
@property (nonatomic, retain) UITabBarController *tabBarController;
@property (nonatomic, retain) UIViewController *controller1;

@property (nonatomic, retain) UIViewController *controller2;
@property (nonatomic, retain) UIViewController *controller3;

// implement
@synthesize tabBarController = _tabBarController;
@synthesize controller1 = _controller1;
@synthesize controller2 = _controller2;
@synthesize controller3 = _controller3;

その後、起動直後に実行されるコードを追加します。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    _window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    _tabBarController = [[UITabBarController alloc] init];
   
   _controller1 = [[UIViewController alloc] init];
    self.controller1.tabBarItem.title = @"タブ1";
   

   _controller2 = [[UIViewController alloc] init];
    self.controller1.tabBarItem.title = @"タブ2";
   
   _controller3 = [[UIViewController alloc] init];
    self.controller1.tabBarItem.title = @"タブ3";

    self.tabBarController.viewControllers =
        [NSArray arrayWithObjects:
         self.controller1,
         self.controller2,
         self.controller3,
         nil];
   
    // delegateを指定することが重要
    self.tabBarController.delegate = self;

    [self.window addSubview:self.tabBarController.view];
    [self.window makeKeyAndVisible];
    return YES;
}

以上のコードで通常のタブバーの表示ができます。
通常のタブバーの使い方ではtabBarControllerのデリゲートを指定する必要はありませんが、この場合は必須です。
ここではタブ2をタッチしたときにモーダルビューが表示されるようにしたいと思います。

デリゲートに指定したためプロトコルを指定します。

@interface FrecoAppDelegate : NSObject
<UIApplicationDelegate,
UITabBarControllerDelegate> {
…
}

そして実装ファイルに以下のコードを加えます。

#pragma mark UITabBarControllerDelegate Methods
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
    if (viewController == self.controller2) {
        UIViewController *controller = [[UIViewController alloc] init];
        [self.controller2 presentModalViewController:controller animated:YES];
        return NO;
    }
   
    return YES;
}

タブをタッチしたときにこのメソッドが呼ばれます。
戻り値はBOOLで、NOを返すことにより、タブ切り替えをキャンセルすることができます。

この場合、self.controller2はほぼダミーになっていますので、ただのUIViewControllerで十分です。実際にはself.controller1,3はUIViewControllerの派生クラスをつかうことになると思います。

もっとスマートな方法をご存じの方がいらっしゃいましたら、コメントで教えていただけるとありがたいです。