24
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

UISplitViewControllerのマスタービュー表示/非表示を切り替える

Last updated at Posted at 2014-04-02

独自の「隠す・表示する」ボタンを配置したいけれど…

UISplitViewControllerのマスタービュー表示/非表示を、ボタンタップではなくプログラムから切り替える方法についてです。

UISplitViewControllerクラスは、-splitViewController:shouldHideViewController:inOrientation:デリゲートメソッドか、デリゲートメソッドに渡されるUIBarButtonItemオブジェクトとを使うことで、Masterビュー(左側に表示されるビュー)の表示/非表示を切り替えられます。たとえば次のようにデリゲートメソッドを実装していると、縦方向の表示のときはMasterビューを隠して画面全体でDetailビュー(右側に表示)を表示できます。

/* orientationで示す方向で、マスタービューを隠すかどうか
 * UISplitViewControllerのビュー表示時、あるいはデバイス方向を変えたときに呼ばれる
 */
- (BOOL)splitViewController:(UISplitViewController *)svc        // ← UISplitViewController
   shouldHideViewController:(UIViewController *)vc              // ← マスタービューのビューコントローラ
              inOrientation:(UIInterfaceOrientation)orientation // ← 方向(UISplitViewController)
{
    // 縦方向のときは隠す。横方向では表示
    return UIInterfaceOrientationIsPortrait(orientation);
}

また、別の-splitViewController:willHideViewController:withBarButtonItem:forPopoverController:デリゲートメソッドで渡されるUIBarButtonItemには、UISplitViewControllerオブジェクトとそのメソッドが、それぞれtargetとactionプロパティにセットされています。そのため、ツールバーやナビゲーションバーにセットしておけば、ユーザーの操作でマスタービューを自由に出したり消したりできます。

- (void)splitViewController:(UISplitViewController *)splitController
     willHideViewController:(UIViewController *)viewController
          withBarButtonItem:(UIBarButtonItem *)barButtonItem
       forPopoverController:(UIPopoverController *)popoverController
{
    NSLog(@"action:[%@] target:[%@]", NSStringFromSelector(barButtonItem.action), barButtonItem.target);
    // → action:[toggleMasterVisible:] target:[<UISplitViewController: 0x…>]
}

ところがここに問題があり、マスタービューの表示を切り替える手段がUIBarButtonItemでしか提供されず、その中で呼んでいるAPIがプライベートAPIなので、プログラムから直接呼ぶことができないのです。
「ある項目を選択したときだけ画面を広くして使いたい」「画面上のツールバーやナビゲーションバー以外のUIでボタンを設置したい」というユースケースはよくありますが、これではそんな要望には応えられません。どうしてこんな設計にしたか分かりませんが、とにかく無理なものは無理です。

ではどうしたらよいか。プライベートAPIを明示的に呼ばず安全に表示/非表示を切り替える方法は、実は簡単な方法があります。次に示すように、barButtonItemのtargetとactionプロパティの情報をそのまま使って、メッセージを送信するだけです。

// UISplitViewControllerにMasterビューの表示切り替えを要求する
// ※ barButtonItemはデリゲートメソッドで届いたときに保持しておく
[barButtonItem.target performSelector:barButtonItem.action];

こうすることで、UISplitViewControllerの内部APIに触れる・知ることなく目的を達成できます。任意のUIやジェスチャでも、ビューの表示を切り替えられますね。

@ikesyo さん、Twitterで困っていたときにコメントしていただき、ありがとうございました。

24
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
25

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?