トップ «前の日記(2012-09-18) 最新 次の日記(2012-09-24)» 編集

Cocoa練習帳

iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど

2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|

2012-09-23 [iOS]独自のコンテナViewController

iOSのCocoa Touchフレームワークには、横並びの画面はTab Bar Controller、階層方向はNavigaton Controllerが用意されているので、画面管理はこれを使えばいいのだが、標準のUIと異なる画面遷移が必要になった際に困ってしまう。

そうなったら、自分でビューの登録削除を行って独自の画面遷移を実装する事になるのだが、せっかくのビューコントローラが有効に活用できなくて残念と感じた事はないだろうか?

iOS 5から、Tab Bar Controllerの様なコンテナViewControllerを独自に実装できる機能がUIViewControllerに追加されたので、それを使って横並びの画面管理を実装してみた。

iOS 5から追加されたコンテナ機能の為のメソッドは、以下の4つ。

  • addChildViewController:
  • removeFromParentViewController
  • willMoveToParentViewController:
  • didMoveToParentViewController:

作成する画面は、灰色のTOPのビューコントローラの配下に赤と青の子ビューコントローラがあって、子っビューコントローラの画面上のボタンを押下すると、画面が切り替わるというものだ。

階層

子ビューコントローラは、それぞれ、独立したStoryboardで作成した。

UIStoryboard    *oneStoryboard = [UIStoryboard storyboardWithName:@"OneStoryboard" bundle:nil];
UIStoryboard    *twoStoryboard = [UIStoryboard storyboardWithName:@"TwoStoryboard" bundle:nil];
OneViewController   *oneViewController = [oneStoryboard instantiateInitialViewController];
TwoViewController   *twoViewController = [twoStoryboard instantiateInitialViewController];

コンテナビューコントローラに子ビューコントローラを登録。

[self addChildViewController:oneViewController];
[self addChildViewController:twoViewController];
oneViewController.cvcViewController = self;
twoViewController.cvcViewController = self;

子ビュコントローラがコンテナビューコントローラ配下になった際の処理は、didMoveToParentViewController:に記述するのだが、コンテナビューコントローラの画面表示が完了した後でないと、addChildViewController:時に自動で呼ばれないようなので、呼ぶ必要がある場合は、自分で呼ぶ事になるようだ。

[oneViewController didMoveToParentViewController:self];
[twoViewController didMoveToParentViewController:self];

ビューコントローラの階層構造を作っても、Viewとは無関係の話。なので、最初の画面を表示するコードを記述しないといけない。

self.selectedViewController = [self.childViewControllers objectAtIndex:0];
[self.view addSubview:self.selectedViewController.view];

画面を切り替えるのは、メソッドtoggleVCで行っている。UIViewControllerには、画面切り替え用のメソッド– transitionFromViewController:toViewController:duration:options:animations:completion:を用意しているが、用意されている画面遷移のアニメーションでないのを望む場合は、自分でなんとかしないといけないようだ。それが、else分の青(two)から赤(one)に切り替わるコードとなる。

- (void)toggleVC
{
    UIViewController    *oneViewController = [self.childViewControllers objectAtIndex:0];
    UIViewController    *twoViewController = [self.childViewControllers objectAtIndex:1];
    if (self.selectedViewController == oneViewController) {
        [self transitionFromViewController:oneViewController
                          toViewController:twoViewController
                                  duration:1.0
                                   options:UIViewAnimationOptionTransitionFlipFromLeft
                                animations:NULL
                                completion:NULL];
        self.selectedViewController = twoViewController;
    }
    else {
        [UIView animateWithDuration:1.0
                         animations:^{
                             CGPoint fromPt = twoViewController.view.layer.position;
                             CGPoint toPt = CGPointMake(fromPt.x, (fromPt.y * -1.0));
                             twoViewController.view.layer.position = toPt;
                         }
                         completion:^(BOOL finished) {
                             /* 元の位置の戻す */
                             CGPoint fromPt = twoViewController.view.layer.position;
                             CGPoint toPt = CGPointMake(fromPt.x, (fromPt.y * -1.0));
                             twoViewController.view.layer.position = toPt;
                             
                             /* 画面遷移(アニメーションなし) */
                             [self transitionFromViewController:twoViewController
                                               toViewController:oneViewController
                                                       duration:0.0
                                                        options:0
                                                     animations:NULL
                                                     completion:NULL];
                         }];
        self.selectedViewController = oneViewController;
    }
}

_ ソースコード

GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/ios/ContainerVC - GitHub

_ 【Cocoa練習帳】

http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)

トップ «前の日記(2012-09-18) 最新 次の日記(2012-09-24)» 編集