人生ずっと勉強

人生ずっと勉強ですね。 https://twitter.com/KiyotakaGoto

モーダルビューの使い方まとめ

ボタンなどを押すと、下からにゅっと出てくるモーダルビューの使い方。

環境

OS X 10.7.5
Xcode 4.6.2
iOS SDK 6.1

プロジェクトの作成

テスト用に、プロジェクトの新規作成から、single-view application を選択しました。
プロジェクト名は「modalViewTest」としました。

storyboard の準備

ViewController がすでに1つ用意されているので、新たにもう1つを追加します。
こうして以下のように、遷移元と遷移先の2つのビューを用意しました。
f:id:kiyotakagoto:20130514233345p:plain


さらに、遷移先の ViewController を追加します。
f:id:kiyotakagoto:20130514233426p:plain
Objective-C class を選択し、UIViewController のサブクラスとして、「modalViewController」を作成します。


storyboard に戻り、遷移先の view のクラスとして先ほど作った modalViewController を選択します。
f:id:kiyotakagoto:20130514233500p:plain


「遷移先へ」ボタンから遷移先のビューへ、「modal」でセグウェイ接続します。
f:id:kiyotakagoto:20130514233513p:plain


さらに、「遷移先へ」ボタンを ViewController に接続します。Action は指定しません。
今回は「transitinoButton」として接続しています。
f:id:kiyotakagoto:20130514233525p:plain


つづいて、「遷移元へ」ボタンを modalViewController に接続します。こちらは Action を選択し、
Event は Touch Up Inside を選択します。
今回は returnButton という名前で接続しています。
f:id:kiyotakagoto:20130514233540p:plain


そして、コードを書いていきます。
[iOS SDK] モーダル modal | hirooka.proを参考にしました。

modalViewController.h

#import <UIKit/UIKit.h>

@protocol ModalViewDelegate <NSObject>
- (void)closeModalView:(NSString *)str;
@end

@interface modalViewController : UIViewController
@property (nonatomic, retain) id delegate;
- (IBAction)returnButton:(id)sender;

@end

modalViewController.m

#import "modalViewController.h"

@implementation modalViewController
@synthesize delegate;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)returnButton:(id)sender {
    [delegate closeModalView:@"return"];
}
@end

ViewController.h

#import <UIKit/UIKit.h>
#import "modalViewController.h" 

@interface ViewController : UIViewController <ModalViewDelegate>
@property (weak, nonatomic) IBOutlet UIButton *transitionButton;

@end

ViewController.m

#import "ViewController.h"

@implementation ViewController
@synthesize transitionButton;

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if( sender == transitionButton ){
        modalViewController *controller = segue.destinationViewController;
        controller.delegate = self;
    }else{
        //
    }
}

- (void)closeModalView:(NSString *)str
{
    [self dismissViewControllerAnimated:YES completion:nil];
    NSLog(@"%@", str);
}

@end

この状態でシミュレータを起動すると、見事「遷移先へ」ボタンを押すと下からにょいっと遷移先ビューが飛び出てきて、
「遷移元へ」ボタンを押すと遷移元のビューが再び現れます。

個人的まとめ

まだちゃんと理解はしていないけど、一応頭の整理として。

遷移元のボタンを押すと prepareForSegue が呼ばれる。
その中で、遷移先の modalViewController を取得、そいつの delegate に遷移元のコントローラを設定。
これをしないと、遷移先へ行けても遷移元へ戻ってこれなくなる。

遷移先で「遷移元へ」ボタンを押すと、returnButton が呼ばれ、
その中で、delegate に対して closeModalView メソッドが呼び出される。
遷移元で定義された closeModalView の中で dismissViewControllerAnimated が実行され、モーダルビューが閉じる、という感じ。
この辺の、モーダルビューに関するやり取りについては、@protocol ModalViewDelegate で予め定義しておかないといけないよう。