【xcode 11】新たに導入されたsceneDelegateの各メソッドが呼ばれるタイミング

環境

xcode 11.0
swift 5.0.1
iOS 13.0

SceneDelegateって何してんの

アプリをつくった段階でデフォルトでつくられるファイルのひとつ。
アプリのUIを複数インスタンスで管理する方法(すなわち複数画面を単体アプリで管理する事と同意)を提供するために、Xcode11 から導入されたUISceneという概念を操作するためのクラス。
アプリ全体のライフタイムイベントを管理する。

UISceneの詳細はここから。

これまでとの違い

これまでは、AppDelegateがアプリのライフタイムイベントを管理していた。それが、SceneDelegateが加わってどう変化したのか。
UISceneの役割等に関しては、以下の記事にわかりやすくまとまっているので割愛。

わかりやすい記事はこちら

ここでは、実際にsceneDelegate内のメソッドがいつ呼び出されるのか、またAppDelegate内のメソッドはどうなっているのか、に関して記述する。

検証結果

まずは、いつどのメソッドが呼ばれるか検証結果からまとめてみた。
検証結果セクション内においては、~~は省略を表す。

アプリ起動時(Not running –> (Inactive –>) Active)

  1. application( didFinishLaunchingWithOptions ) (AppDelegate内メソッド)
  2. application( configurationForConnecting ) (AppDelegate内メソッド)
  3. scene( willConnectTo session ) (SceneDelegate内メソッド)
  4. viewDidLoad() (viewController内メソッド)
  5. sceneWillEnterForeground(_ scene: UIScene) (SceneDelegate内メソッド)
  6. sceneDidBecomeActive(_ scene: UIScene) (SceneDelegate内メソッド)

アプリをバックグラウンドに持って行った時(Active –> (Inactive –>) Background)

  1. sceneWillResignActive(_ scene: UIScene) (SceneDelegate内メソッド)
  2. sceneDidEnterBackground(_ scene: UIScene) (SceneDelegate内メソッド)

アプリがバックグラウンドから復帰した時(Background –> (Inactive –>) Active)

  1. sceneWillEnterForeground(_ scene: UIScene) (SceneDelegate内メソッド)
  2. sceneDidBecomeActive(_ scene: UIScene) (SceneDelegate内メソッド)

アプリを終了した時(Background –> (Suspended –>) Not Running)

  1. sceneDidDisconnect(_ scene: UIScene) (SceneDelegate内メソッド)
  2. application( didDiscardSceneSessions ) (AppDelegate内メソッド)

わかったこと

・ 基本的に、AppDelegateはアプリの起動・終了時に呼ばれるのみ。
・ アプリ起動中の状態変化に対応するのは、SceneDelegate

おまけ(検証方法)

コードに以下のように記述を付け加え、どのタイミングで各メソッドが呼ばれるかを検証した。

コード

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        print("アプリが起動されたよ") //<- 書き足した

        return true
    }

    // MARK: UISceneSession Lifecycle
    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        // Called when a new scene session is being created.
        // Use this method to select a configuration to create the new scene with.

        print("scene呼び出し中") //<- 書き足した

        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
    }

    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
        // Called when the user discards a scene session.
        // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
        // Use this method to release any resources that were specific to the discarded scenes, as they will not return.

        print("アプリが閉じられたよ") //<- 書き足した
    }


}
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?


    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).

        print("sceneが呼ばれたよ") //<- 書き足した

        guard let _ = (scene as? UIWindowScene) else { return }

    }

    func sceneDidDisconnect(_ scene: UIScene) {
        // Called as the scene is being released by the system.
        // This occurs shortly after the scene enters the background, or when its session is discarded.
        // Release any resources associated with this scene that can be re-created the next time the scene connects.
        // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).

        print("sceneが閉じられるよ") //<- 書き足した
    }

    func sceneDidBecomeActive(_ scene: UIScene) {
        // Called when the scene has moved from an inactive state to an active state.
        // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.

        print("sceneがactiveになったよ") //<- 書き足した
    } 

    func sceneWillResignActive(_ scene: UIScene) {
        // Called when the scene will move from an active state to an inactive state.
        // This may occur due to temporary interruptions (ex. an incoming phone call).

        print("sceneがinactiveになったよ") //<- 書き足した
    }

    func sceneWillEnterForeground(_ scene: UIScene) {
        // Called as the scene transitions from the background to the foreground.
        // Use this method to undo the changes made on entering the background.

        print("sceneがforegroundにきたよ") //<- 書き足した
    }

    func sceneDidEnterBackground(_ scene: UIScene) {
        // Called as the scene transitions from the foreground to the background.
        // Use this method to save data, release shared resources, and store enough scene-specific state information
        // to restore the scene back to its current state.

        print("sceneがbackgroundになったよ") //<- 書き足した
    }
}
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        print("viewが呼び出されたよ") //<- 書き足した
    }
}

結果

・アプリ起動時
スクリーンショット 2019-10-13 18.47.05.png

・shift + command + h でホーム画面に移行した時
スクリーンショット 2019-10-13 18.48.58.png

・その状態からまた起動した時
スクリーンショット 2019-10-13 18.50.03.png

・アプリを閉じた時
スクリーンショット 2019-10-13 18.51.10.png

参考文献

各メソッドの記述の意味とかまで詳しく説明されててわかりやすいページ

SwiftUIを触って分かったこと:①初期画面の設定方法

AppDelegate内のメソッドが呼ばれるタイミングを調査していたページ

AppDelegateのメソッドが呼ばれるタイミングと実装すべき内容(iOS11)

今回の記事の参考にしたページ

【iOS】AppDelegate.swiftってなにしてんの?

domain取得はxdomain → https://www.xdomain.ne.jp/