21
34

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.

【iOS】私が薦める画面遷移方法

Last updated at Posted at 2017-02-05

皆さんは画面遷移を定義する時、StoryboardのSegueを使っていますか? 僕はこのSegueというやつがどうも好きになれず、コードで画面遷移を定義しています。

スクリーンショット 2017-02-05 16.28.21.png

上図のように、画面A -> 画面B -> 画面Cとシンプルな遷移のみのアプリならばSegueは良いかもしれません。しかし、本格的なアプリを作っていくと、どうしても画面Aから画面Cへ飛ばないと要件を満たせないといったことがあります。画面数も増えると、Segueの線もタコ足配線のようにゴチャゴチャした感じに引かれ、見辛くなっていきます。
実際の作業面で言えば、13インチMacBookのような狭いスクリーン上で線を引っ張ってViewController同士をつなげる作業はけっこうストレスです…

なので、僕はSegueを使わず、コードで画面遷移させる方法を薦めています。

ただ、Storyboardを完全に使わないというわけではありません。ViewのレイアウトはStoryboardを使った方がやはり楽だと思います。

この記事では画面遷移のみをコードで定義する方法を紹介します。

Step1: Storyboard上の設定

まずはじめに、Main.storyboardにサインイン画面を作っているとします。この画面はユーザが未サインイン状態の時に、サインイン無しでは利用できない画面(例えば、プロフィール画面や購入画面)から呼び出されます。

下図のように、サインイン画面用のViewControllerを選択して、右パネル上のCustom ClassのClassにこのViewControllerのクラス名を入力します。
例) SignInViewController
IdentityのStoryboard IDには任意のユニークとなる文字列を入力します。
例) SignIn

スクリーンショット 2017-02-05 17.09.27.png

Step2: 遷移先のViewControllerの実装

ヘッダファイルにはSignInViewControllerクラスのインスタンスを生成するクラスメソッドだけを定義します。このメソッドではNSString型のメッセージを引数として受け取るようにしています。

SignInViewController.h
# import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface SignInViewController : UIViewController

+ (instancetype)instantiateViewControllerWithMessage:(NSString *)msg;

@end

NS_ASSUME_NONNULL_END

実装は以下のようにします。

SignInViewController.m
# import "SignInViewController.h"

@interface SignInViewController ()

@property (nonatomic) NSString *msg;

@end

@implementation SignInViewController

+ (instancetype)instantiateViewControllerWithMessage:(NSString *)msg {
    // SignInViewControllerのインスタンスを生成
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    SignInViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"SignIn"];
    
    // 画面遷移アニメーションの設定(お好きなものを)
    vc.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    
    // 遷移元から渡された値を保持
    vc.msg = msg;
    
    return vc;
}

...

@end

storyboardWithName:メソッドの引数にはStoryboard名を指定します。Main.storyboardならMain
instantiateViewControllerWithIdentifier:メソッドの引数にはStep1で設定したStoryboard IDを指定します。

この方法の気に入っている点は、安易にViewControllerのプロパティを外部に公開しなくて済むことです。readwriteなmsgプロパティを.hファイルに書かない。
メソッド名から遷移先に渡さないといけない値が何かも理解しやすいです。

Step3: 遷移元のViewControllerの実装

例えば、購入画面を表示する時、ユーザが未サインイン状態だったのでサインイン画面へ遷移させます。

BuyViewController.m
...

# import "SignInViewController.h"

...

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    if (/*サインインしていない*/) {
        // サインイン画面へ
        id vc = [SignInViewController instantiateViewControllerWithMessage:@"購入するためにはサインインしてください"];
        [self presentViewController:vc animated:YES completion:nil];
    }
}

...

とても簡単です。画面遷移させたいところで2,3行のコードを書くだけです。
上の例はモーダル遷移ですが、NavigationController配下では、

[self.navigationController pushViewController:vc animated:YES];

とすればプッシュ遷移します。

遷移元の画面へ戻る時は、モーダル遷移ならば、

[self dismissViewControllerAnimated:YES completion:nil];

プッシュ遷移ならば、

[self.navigationController popViewControllerAnimated:YES];

を実行すればいいわけです。

いかがでしたか? Segueを使うよりもスマートだと思いませんか。
少しでもiOS開発のご参考になれば幸いです。

21
34
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
21
34

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?