📲

windowのrootViewControllerを変更して画面遷移する方法

2022/06/20に公開

新しい画面遷移の方法を学んだから半分メモ書き感覚で書いていくで〜
訂正、編集リクエスト、感激やで〜

目的

作成したいものは以下のように、ボタンを押したら画面遷移する機能。

これを、Segue等を使わないやり方で画面遷移させる。
要は、RootViewControllerを使ってアニメーションで画面遷移をさせる。

環境

  • macOS Monterey: Version12.4
  • Xcode: Version 13.4.1
  • Swift: Version 5.6.1

前提

コチラの記事を参考に、

  1. AppDelegateから// MARK: UISceneSession Lifecycle以降のコードを削除する
  2. AppDelegateにwindowプロパティを追加
  3. Info.plistからUIApplicationSceneManifestを全て削除
  4. SceneDelegate.swiftを削除する

を行います。
正直、削除してもしなくても良いが、2のwindowプロパティだけは追加していて欲しい。

なので、AppDelegate.swiftは、

AppDelegate.swift
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        return true
    }
}

となっている。

Storyboardでの設定

ViewControllerを追加していく。今回はわかりやすいように、青、黄、赤の画面をそれぞれ、FirstViewController, SecondViewController, ThirdViewControllerとした。
スクリーンショット 2022-06-16 22.29.01.png

次に、ボタンを押すと画面遷移するようにボタンを配置していく。配置したものがコチラ↓
スクリーンショット 2022-06-16 22.32.41.png
最後に、Storyboard IDを設定する。
今回は、FirstViewController, SecondViewController, ThirdViewControllerなので、順番にFirstVC, SecondVC, ThirdVCとする。

これで準備はOK。特にStoryboard IDを設定は忘れないように

AppDelegateでの設定

AppDelegate.swift
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
+    let storyboard = UIStoryboard(name: "Main", bundle: nil)

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+        self.window = UIWindow(frame: UIScreen.main.bounds)
+        self.window?.makeKeyAndVisible()
+        let initialViewController = self.storyboard.instantiateViewController(withIdentifier: "FirstVC")
+        self.window?.rootViewController = initialViewController

        return true
    }
    
+    func switchViewController(identifier: String) {
+        UIView.transition(with: self.window!, duration: 0.5, options: .transitionCrossDissolve, animations: {
+            let oldState: Bool = UIView.areAnimationsEnabled
+            UIView.setAnimationsEnabled(false)
+            self.window?.rootViewController = self.storyboard.instantiateViewController(withIdentifier: identifier)
+            UIView.setAnimationsEnabled(oldState)
+        }, completion: nil)
+    }
}

ViewControllerでの設定

UIパーツとコードを紐付けすると、↓のようになる

 FirstViewController
import UIKit

final class FirstViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }
    
+   @IBAction private func goToSecondVCButton(_ sender: Any) {
+   }
    
}

メソッドの命名が無茶苦茶なのはご愛嬌ということで💦

次に、画面遷移をさせるために、func goToSecondVCButtonに先ほど作成したfunc switchViewController(identifier: String)を呼ばせる。

そうすると、↓のようになる。

FirstViewController
import UIKit

final class FirstViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }
    
    @IBAction private func goToSecondVCButton(_ sender: Any) {
+        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
+        appDelegate.switchViewController(identifier: "SecondVC")
    }
}

同様のことをSecondViewController, ThirdViewControllerにも行う。

SecondViewController
import UIKit

final class SecondViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }
    
+    @IBAction private func goToThirdVCButton(_ sender: Any) {
+        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
+        appDelegate.switchViewController(identifier: "ThirdVC")
+    }
}
ThirdViewController
import UIKit

final class ThirdViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

+    @IBAction private func goToFirstVCButton(_ sender: Any) {
+        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
+        appDelegate.switchViewController(identifier: "FirstVC")
+    }
}

これで、Segueを使わずにRootViewControllerをアニメーションで画面遷移することができた。

参考文献

https://en.swiswiswift.com/2019-02-01/

https://qiita.com/tomu28/items/4bb327a8f80c042e41a1

Discussion