swift

【Swift】コードで行う画面遷移のやり方

segueを使った画面遷移はコンフリクト地獄の始まりなので避けるのが無難です。

コードで行う2種類の画面遷移

そもそもiOSにおける画面遷移には大きく分けて二つの方法があります。若干挙動が異なります。

  1. UINavigationControllerを使った画面遷移

    pushViewControllerというメソッドを呼び出すことで画面遷移を行います。これは横方向への遷移で、本のページを捲るような挙動になります。

    func pushViewController(_ viewController: UIViewController, animated: Bool)
  2. UIViewControllerを使った画面遷移

    present というメソッドを呼び出すことで画面遷移を行います。こちらは元々のViewの上に重なるように新しい画面が出てくるという挙動です。

    func present(_ viewControllerToPresent: UIViewController, 
                animated flag: Bool, completion: (() -> Void)? = nil)

両者の共通点

上記のメソッドのコードを比較すると、どちらのメソッドも遷移先のUIViewControllerを第一引数に渡す必要があることがわかります。そして遷移先のViewControllerをコードで取得するには、以下のような工程を踏む必要があります。

画面遷移の工程

  1. 遷移先のStoryboardを取得する
  2. 取得したStoryboardから、ViewControllerをインスタンス化する
  3. 遷移のメソッドを実行する
手順解説

このことを踏まえ、上記の3工程に分けて手順を説明していきます。ここではMainViewControllerからNextViewControllerへ遷移するものとしてコードを紹介しています。

前準備

  • 新しくプロジェクトを作成します。
  • 新しくNextViewController.swiftという名前のViewControllerを作成します。
  • 新しくNext.storyboardという名前のStoryboardを作成し、中にViewControllerを設置します。
  • Storyboardに設置したViewControllerとNextViewControllerとの関連付けを行っておきます。

①遷移先のStoryboardを取得する

まずは遷移先のstoryboardを取得します。例えば遷移先のStoryboardのファイル名がNext.storyboardの場合、引数nameの値は"Next"になります。

let storyboard = UIStoryboard(name: "Next", bundle: nil)

②取得したStoryboardから遷移先のViewControllerをインスタンス化

次に手順1で取得したstoryboardからViewControllerをインスタンス化します。ViewControllerをインスタンス化するにはinstantiateInitialViewControllerというメソッドを呼び出します。

遷移先のViewControllerにEntry Pointをつける

遷移先のStoryboard内のViewControllerを選択し、右メニューの「Is Initial ViewController」にチェックマークをつけよう。下の画像のように「→」マークが確認できればおk。 enter image description here

ViewControllerをインスタンス化する

instantiateInitialViewController()はentrypointが付いているViewControllerをインスタンス化することができるメソッドです。キャストすることで遷移先のViewControllerが持つプロパティを参照できるようになります。

let storyboard = UIStoryboard(name: "Next",bundle: nil)  //手順1で説明済
guard let viewController = storyboard.instantiateInitialViewController() as? NextViewController else { return }  //インスタンス化したものを定数viewControllerとして定義

注) 返り値型Optionalに注意!!

instantiateInitialViewController()の返り値がOptional型であることに注意してください。返り値がoptiona lの場合は下のような強制アンラップは使わずに、if letあるいはguard letを使った安全なアンラップを行うのが定石です。
Optionalとその扱い方について良くわからないという人はオプショナルについての解説を見ておくことをお勧めします。

③遷移のコードを記述する

遷移したいViewControllerのインスタンス化が完了した後は、任意のタイミングで実際に遷移を行うメソッドを呼び出します。遷移の方法として冒頭で紹介した2パターンをそれぞれ解説します。

A. NavigationControllerで遷移したい場合

Storyboard内の遷移元となるViewControllerを選択した状態で「Editor」→「Embed In」→「Navigation Controller」と選びます embed in

するとStoryboard内にNavigationControllerが追加され、ViewControllerと接続された状態となります。あとはコードを書くだけです。コードでは次のように遷移します。 "Next"の部分は適宜書き換えてください

let storyboard = UIStoryboard(name: "Next",bundle: nil)
guard let viewController =  storyboard.instantiateInitialViewController() as? NextViewController else { return }

navigationController?.pushViewController(viewController, animated: true)  //ココ

B. ViewControllerのメソッドで遷移したい場合

こちらは簡単です。次のようなコードを書くだけです。"Next"の部分は適宜書き換えてください

let storyboard = UIStoryboard(name: "Next",bundle: nil)
guard let viewController =  storyboard.instantiateInitialViewController() as? NextViewController else { return }

present(viewController, animated: true) //ココ
よくあるエラーの紹介

最後に起こりがちなエラーについて紹介しておきます。主に次のエラーが起こりがちです。

  • 遷移先のViewControllerにEntrypointをつけ忘れる
    右メニューの「Is Initial View Controller」にチェックマークをつけ忘れがちです。Entry PointがないとinstantiateInitialViewControllerの返り値がnilになってしまいます。
  • 遷移元のnavigationControllerを埋め込み忘れる
    navigationControllerで遷移したい場合、ViewControllerへの埋め込みを忘れるとnavigatoinController?の値がnilになってしまうよ。するとnavigationController?.pushViewControllerが実行されずに、結果遷移できないよ。(詳しくはOptionalChainingの解説を参照)

まとめ

書いたことの簡単なまとめ

  • コードでの遷移はpushViewControllerpresentどちらかのメソッドを呼び出して行う
  • この二つのメソッドを呼び出す前に、instantiateInitialViewController()で遷移先のViewControllerをインスタンス化しておく必要がある
  • 「EntryPoint」・「NavigationController」のつけ忘れには注意する

読んでいただきありがとうございます!!

記事として取り上げたトピックを体系化してまとめた内容を電子書籍として販売しています。購入していただくことで執筆の応援ができます。詳細はこちらから