[Swift]「ライフサイクル」

この記事では、SwiftのViewControllerライフサイクルと、アプリライフサイクルについて網羅的に解説します。

Viewやアプリの起動から終了までの流れについて、重要な要素であるViewControllerSceenDelegateAppDelegateクラスの各メソッドの役割などを具体的に紹介します。

目次

ViewControllerのライフサイクル

iOSアプリの画面はViewControllerが管理しています。
ViewControllerのライフサイクルを理解することは、画面の表示や操作を制御する上で非常に重要です。

この章では、ViewControllerのライフサイクルについて詳しく解説します。

メソッドの紹介

STEP
初回Viewロード時(viewDidLoad)

まず、ViewControllerが初めてメモリにロードされるときにviewDidLoadメソッドが呼ばれます。

viewDidLoadメソッドは、Viewがロードされた後に実行される初期化処理を記述する場所です。例えば、データの読み込みUIの初期化など、Viewが表示される前に行いたい処理を実装します。

以下に示すコードは、viewDidLoadメソッドの実装例です。

override func viewDidLoad() {
    super.viewDidLoad()
    // Viewがロードされた後に実行される初期化処理を記述する
    
    // 例: データの読み込みやUIの初期化など
}
STEP
View画面が表示される直前(viewWillAppear)

Viewが画面に表示される直前にviewWillAppearメソッドが呼ばれます。

viewWillAppearメソッドは、Viewが表示される直前に実行される処理を記述する場所です。例えば、データの更新UIの更新など、Viewが表示される前に行いたい処理を実装します。

以下に示すコードは、viewWillAppearメソッドの実装例です。

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    // Viewが表示される直前に実行される処理を記述する
    
    // 例: データの更新やUIの更新など
}
STEP
View画面が表示後(viewDidAppear)

Viewが画面に表示された後にviewDidAppearメソッドが呼ばれます。

viewDidAppearメソッドは、Viewが表示された後に実行される処理を記述する場所です。例えば、アニメーションの開始ユーザーへの表示など、Viewが表示された後に行いたい処理を実装します。

以下に示すコードは、viewDidAppearメソッドの実装例です。

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    // Viewが表示された後に実行される処理を記述する
    
    // 例: アニメーションの開始やユーザーへの表示など
}
STEP
View画面が消える直前(viewWillDisappear)

Viewが画面から消える直前にviewWillDisappearメソッドが呼ばれます。

viewWillDisappearメソッドは、Viewが画面から消える直前に実行される処理を記述する場所です。例えば、データの保存アニメーションの停止など、Viewが画面から消える前に行いたい処理を実装します。

以下に示すコードは、viewWillDisappearメソッドの実装例です。

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    // Viewが消える直前に実行される処理を記述する
    
    // 例: データの保存やアニメーションの停止など
}
STEP
View画面が消えた後(viewDidDisappear)

Viewが画面から消えた後にviewDidDisappearメソッドが呼ばれます。

viewDidDisappearメソッドは、Viewが画面から消えた後に実行される処理を記述する場所です。例えば、リソースの解放終了処理など、Viewが画面から消えた後に行いたい処理を実装します。

以下に示すコードは、viewDidDisappearメソッドの実装例です。

override func viewDidDisappear(_ animated: Bool) {
    super.viewDidDisappear(animated)
    // Viewが消えた後に実行される処理を記述する
    
    // 例: リソースの解放や終了処理など
}

動作確認

ViewControllerサイクルを簡単なプログラムを作成して、実際にどのよう動くのか検証してみました。

STEP
アプリ起動時→下図の赤枠①

①viewDidLoad:画面1の初期起動
②viewWillAppear:画面1の表示直前
③viewDidAppear:画面1の表示後
まで実行

STEP
画面1でNextボタンクリック後→下図の青枠②

 ①viewDidLoad:画面2の初期起動
④viewWillDisappear:画面1の消える直前
 ②viewWillAppear:画面2の表示直前
 ③viewDidAppear:画面2の表示後
⑤viewDidDisappear:画面1の消えた後
まで実行

STEP
画面2でBackボタンクリック後→下図の緑枠③

 ④viewWillDisappear:画面2の消える直前
②viewWillAppear:画面1の表示直前
③viewDidAppear:画面1の表示後
 ⑤viewDidDisappear:画面2の消えた後
まで実行

①viewDidLoad:画面1の初期起動は発動しない(STEP1の1回のみ)

画面1
画面2
①アプリ起動時
②画面1でNextボタンクリック後
③画面2でBackボタンクリック後
ViewController1 →画面1
ViewController2 →画面2

アプリのライフサイクル

iOSアプリの開発において、アプリのライフサイクルを理解することは非常に重要です。

アプリのライフサイクルに関する知識を持つことで、適切なタイミングで必要な処理を実行することができます。この記事では、アプリが起動され、バックグラウンドで実行され、終了するまでの流れを詳しく解説します。

SceneDelegateの導入について

以前は、AppDelegateアプリ全体のライフサイクル管理を担っていました。しかし、iOS13からは複数のウィンドウやシーンがサポートされるようになり、それに伴いSceneDelegateが導入されました。

SceneDelegateは、個々のシーンの管理やウィンドウの設定、ユーザーの操作に応じた処理など、細かなレベルでの制御を可能にします。SceneDelegateの導入により、より柔軟で拡張性の高いアプリケーションを開発することができるようになりました。

以前のAppDelegateSceneDelegateの主な違いについて
  1. シーンベースのアプリケーション:
    SceneDelegate
    は、複数のウィンドウやシーンを持つアプリをサポートすることができます。
    以前のAppDelegateは、シングルウィンドウのアプリケーションに特化していました。
  2. シーンライフサイクルの管理:
    SceneDelegateは、各シーンのライフサイクルイベントに対する処理を管理します。例えば、シーンがアクティブになったときや非アクティブになったとき、バックグラウンドに移行したときなどのイベントに対して、適切な処理を実行することができます。
    一方、以前のAppDelegateはアプリケーション全体のライフサイクルに関与していました。
  3. シーンの作成と管理:
    SceneDelegateは、シーンの作成や管理に関する責任を持ちます。アプリが起動すると、SceneDelegateのscene(_:willConnectTo:options:)メソッドが呼び出され、新しいシーンがアプリに接続される前に必要な初期化や設定を行うことができます。また、複数のシーンを持つ場合には、シーン間の情報共有や切り替えをサポートします。
  4. UIWindowSceneの管理:
    SceneDelegateは、新たに導入されたUIWindowSceneオブジェクトを管理します。これにより、複数のウィンドウを持つアプリケーションをサポートすることができます。ウィンドウの作成や設定、表示の制御などをSceneDelegateを通じて行います。
    以前のAppDelegateでは、UIWindowの作成や管理を行っていましたがSceneDelegateによってウィンドウシーンが追加され、その管理がSceneDelegateに移行しました。

アプリの起動から終了までの詳細なライフサイクルについて

アプリのライフサイクルの一般的な流れは以下の通りです。

  1. App Launched:アプリの起動
  2. App Visible:アプリが見えるようになる
  3. App Recedes into Background:アプリがバックグラウンドに退く
  4. Resources Reclaimed:アプリが終了し、他のアプリにリソースを開放する

iOSアプリにおいて、これらのアプリのライフサイクルのメソッドは、AppDelegateSceneDelegateファイルにありますので、コード事例を交えながら初心者にもわかりやすく解説します。

AppDelegateクラスのメソッドの紹介

STEP
アプリの起動処理(didFinishLaunchingWithOptions)

アプリが起動すると、AppDelegateクラスのdidFinishLaunchingWithOptionsメソッドが呼び出されます。

ここでは、アプリの初期設定必要なリソースの読み込みなどを行います。

以下は、実際のコード例です。

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

    // アプリの初期設定
    // リソースの読み込み
    // その他の起動処理

    return true
}
STEP
アプリの終了処理(applicationWillTerminate)

アプリが終了する直前には、AppDelegateクラスのapplicationWillTerminateメソッドが呼び出されます。ここでは、

アプリの終了時に必要なクリーンアップ処理データ保存などを行います。

以下は、実際のコード例です。

func applicationWillTerminate(_ application: UIApplication) {
    // アプリが終了する直前の処理
    // クリーンアップ処理やデータの保存など
}
STEP
シーンの接続設定(configurationForConnecting)

シーンの接続設定に関する処理は、AppDelegateクラスconfigurationForConnectingメソッドで行います。

このメソッドでは、シーンが接続される際の設定情報接続処理のカスタマイズを行います。

以下は、実際のコード例です。

func scene(_ scene: UIScene, 
    configurationFor connectingSceneSession: UISceneSession, 
    options: UIScene.ConnectionOptions) 
    -> UISceneConfiguration {

    // シーンの接続設定情報やカスタマイズ処理
    // デフォルトの設定や独自の設定など

    return UISceneConfiguration(
        name: "CustomSceneConfiguration", 
        sessionRole: connectingSceneSession.role)
}
STEP
シーンセッションの破棄(didDiscardSceneSessions)

シーンセッションが破棄されると、AppDelegateクラスdidDiscardSceneSessionsメソッドが呼び出されます。

このメソッドでは、破棄されたシーンセッションに関する後処理データの保存などを行います。

以下は、実際のコード例です。

func application(_ application: UIApplication, 
    didDiscardSceneSessions sceneSessions: 
    Set<UISceneSession>) {
    // シーンセッションが破棄される時の処理
    // 後処理やデータの保存など
}

SceneDelegateクラスのメソッドの紹介

STEP
シーンの作成とウィンドウの表示(willConnectTo)

アプリが起動し、シーンが作成される際には、SceneDelegateクラスのscene(_:willConnectTo:options:)メソッドが呼び出されます。

ここでは、シーンの初期設定ウィンドウの表示などを行います。

以下は、実際のコード例です。

func scene(_ scene: UIScene, 
    willConnectTo session: UISceneSession, 
    options connectionOptions: UIScene.ConnectionOptions) {

    guard let windowScene = (scene as? UIWindowScene) 
        else { return }
    
    // シーンの初期設定
    // ウィンドウの作成と表示
    // その他のシーンに関する処理
}
STEP
シーンのアクティブ化(sceneDidBecomeActive)

シーンがアクティブになると、SceneDelegatesceneDidBecomeActiveメソッドが呼び出されます。

ここでは、アクティブになったシーンに関連する処理画面の更新を行います。

以下は、実際のコード例です。

func sceneDidBecomeActive(_ scene: UIScene) {
    // シーンがアクティブになった時の処理
    // 画面の更新や再生開始など
}
STEP
シーンの非アクティブ化とバックグラウンド移行(sceneWillResignActive)

シーンが非アクティブになり、バックグラウンドに移行する際には、SceneDelegatesceneWillResignActiveメソッドが呼び出されます。

ここでは、非アクティブ化に伴う処理データ保存などを行います。

以下は、実際のコード例です。

func sceneWillResignActive(_ scene: UIScene) {
    // シーンが非アクティブになる前の処理
    // データの保存や停止処理など
}
STEP
フォアグラウンド移行(sceneWillEnterForeground)

バックグラウンドからアプリがフォアグラウンドに移行すると、SceneDelegatesceneWillEnterForegroundメソッドが呼び出されます。

ここでは、フォアグラウンド移行時に必要な処理データの読み込みなどを行います。

以下は、実際のコード例です。

func sceneWillEnterForeground(_ scene: UIScene) {
    // アプリがフォアグラウンドに移行する前の処理
    // データの読み込みや再開処理など
}
STEP
バックグラウンド移行(sceneDidEnterBackground)

ユーザーがホームボタンを押してアプリをバックグラウンドに移行すると、SceneDelegatesceneDidEnterBackgroundメソッドが呼び出されます。

このメソッドでは、バックグラウンド移行時に必要なデータ保存処理の停止などを行います。

以下は、実際のコード例です。

func sceneDidEnterBackground(_ scene: UIScene) {
    // シーンがバックグラウンドに移行する時の処理
    // データの保存や停止処理など
}
STEP
シーンの終了処理(sceneDidDisconnect)

アプリが終了するか、シーンが破棄されると、SceneDelegatesceneDidDisconnectメソッドが呼び出されます。

ここでは、シーンの終了時に必要な後処理データ保存などを行います。

以下は、実際のコード例です。

func sceneDidDisconnect(_ scene: UIScene) {
    // シーンが破棄される時の処理
    // 後処理やデータの保存など
}

AppDelegateSceneDelegateの動作確認

AppDelegateSceneDelegateの動きを確認するため、簡単なプログラムを作成しました。

AppDelegateSceneDelegateの動きを確認するため、ViewControllerライフサイクルの動作確認時に使用したプログラム(ViewController1ViewController2)に、AppDelegateAppDelegateを追加しました。

AppDelegateSceneDelegateの動作確認

AppDelegateSceneDelegateの各メソッドにもprint文を追記します。

AppDelegate
SceneDelegate
ViewController1 →画面1
ViewController2 →画面2

各時点の検証結果は以下の通りです。

STEP
アプリ起動時
  • viewDidLoadが呼び出される前に、didFinishLaunchingWithOptions(アプリ起動)、willConnectTo(シーン作成)が発動します。
  • viewWillAppearとviewDidAppearの間に、sceneWillEnterForeground(フォアグラウンドへ)、sceneDidBecomeActive(アクティブへ)が発動しています。
STEP
画面1でNextボタンクリック後
  • AppDelegateとSceneDelegateのメソッドの発動はありません。
STEP
別のアプリに切り替え後
  • sceneWillResignActive(非アクティブへ)、sceneDidEnterBackground(バックグラウンドへ)が発動しています。
STEP
アプリをアクティブ後
  • sceneWillEnterForeground(フォアグラウンドへ)、sceneDidBecomeActive(アクティブへ)が発動しています。
STEP
アプリを終了後
    • viewWillDisappear前に、sceneWillResignActive(非アクティブへ)、sceneDidDisconnect(シーン切断へ)、didDiscardSceneSessions(シーン終了へ)が発動しています。
    • viewDidDisappear後に、
      applicationWillTerminate(アプリ終了へ)が発動しています。

ユーザーイベントの処理方法

バックグラウンド実行とフォアグラウンド実行

バックグラウンド実行フォアグラウンド実行について、初心者にもわかりやすく解説します。

アプリがバックグラウンドで実行される場合フォアグラウンドで実行される場合には、処理の違いや注意点があります。これらを理解することで、アプリの振る舞いを適切に管理することができます。

STEP
バックグラウンド実行

バックグラウンドでの実行とは、ユーザーがアプリを最小化したり、別のアプリに切り替えたりした場合に、アプリが裏側で動作し続けることを指します。

例えば、音楽プレーヤーアプリがバックグラウンドで再生を続けたり、通知を受け取ったりするのはその一例です。バックグラウンド実行では、アプリが使用するリソースの制限があるため、適切な処理の実装が必要です。

具体的なコード事例を交えて説明します。

バックグラウンド実行
func applicationDidEnterBackground(_ application: UIApplication) {
    // バックグラウンドへの切り替え時に実行する処理
    // 例えば、データの保存やタイマーの停止など
}
  • applicationDidEnterBackgroundメソッドは、アプリがバックグラウンドになった時に呼ばれるメソッドです。
  • このメソッド内では、バックグラウンドへの切り替え時に必要な処理(例えば、データの保存やタイマーの停止など)を実装します。
  • sceneDidEnterBackgroundは、SceneDelegateクラス内で実装され、シーンがバックグラウンドに移行する際に呼び出されます。
  • applicationDidEnterBackgroundは、AppDelegateクラス内で実装され、アプリ全体がバックグラウンドに移行する際に呼び出されます。
STEP
フォアグラウンド実行

フォアグラウンド実行とは、ユーザーがアプリをアクティブな状態で使用している場合を指します。

画面上に表示され、ユーザーの操作に応じた処理を行います。フォアグラウンド実行中は、アプリがメインスレッドで実行されるため、UIの更新やユーザーの入力に対するレスポンスなどを行うことができます。

具体的なコード事例を交えて説明します。

フォアグラウンド実行
func applicationWillEnterForeground(_ application: UIApplication) {
    // フォアグラウンドへの切り替え時に実行する処理
    // 例えば、データの更新やUIの状態の復元など
}
  • applicationWillEnterForegroundメソッドは、アプリがフォアグラウンドになる直前に呼ばれるメソッドです。
  • このメソッド内では、フォアグラウンドへの切り替え時に必要な処理(例えば、データの更新やUIの状態の復元など)を実装します。
  1. sceneWillEnterForegroundは、SceneDelegateクラス内で実装され、シーンがフォアグラウンドに移行する際に呼び出されます。
  2. applicationWillEnterForegroundは、AppDelegateクラス内で実装され、アプリ全体がフォアグラウンドに移行する際に呼び出されます。

アプリの終了と再起動

アプリの終了と再起動が重要な手法である理由は以下の通り。

  1. ユーザーエクスペリエンスの向上:
    アプリを正確に終了させることで、ユーザーはアプリの挙動を意図通りに制御できます。
    適切に終了させることでリソースの浪費を防ぎ、ユーザーのデバイスのパフォーマンスやバッテリー寿命を向上させることができます。
  2. メモリ管理の最適化:
    アプリの終了と再起動によって、メモリの解放やリセットが行われます。
    正確に終了させることで、メモリを最適化し、アプリの動作をスムーズに保つことができます。
  3. アプリの状態のリセット:
    再起動は、アプリの状態を初期状態に戻すための手段として重要です。
    一部のアプリでは、特定の条件下で正常に動作しなくなる場合があります。そのような場合、アプリを再起動することで問題を解消することができます。

まず、アプリを終了させる方法です。以下のコードをご覧ください。

アプリを終了させる方法
func exitApp() {
    UIControl().sendAction(
    #selector(NSXPCConnection.suspend), 
    to: UIApplication.shared, 
    for: nil)
}
  • exitAppというメソッドを作成しています。
  • このメソッド内で、UIControl().sendAction(_:to:for:)を使用して、NSXPCConnection.suspendというアクションをUIApplication.sharedに送信しています。
  • これにより、アプリが終了されます。

次に、アプリを再起動させる方法です。以下のコードを参考にしてください。

アプリを再起動させる方法
func restartApp() {
    if let window = UIApplication.shared.windows.first {
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let initialViewController = storyboard.instantiateInitialViewController()
        window.rootViewController = initialViewController
        window.makeKeyAndVisible()
    }
}
  • restartAppというメソッドを作成しています。
  • このメソッド内で、UIApplication.shared.windows.firstを使用して、アプリの最初のウィンドウを取得します。
  • そして、UIStoryboardを使用してメインのストーリーボードを読み込み、instantiateInitialViewControllerを呼び出して初期のビューコントローラーを取得します。
  • 最後に、ウィンドウのrootViewControllerを初期のビューコントローラーに設定し、makeKeyAndVisibleを呼び出してウィンドウを表示します。
  • これにより、アプリが再起動されます。

この記事が気に入ったら
いいね または フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次