iOSにおけるViewController Lifecycle: 主要な概念、段階、メソッド

著者: IT Sectr 公開日: 2026-03-05 読了時間: 9 分

ViewController Lifecycleとは、UIKitがiOSの画面管理時に自動的に呼び出すメソッドのシーケンスです。Appleドキュメントによると、各UIViewControllerはViewの作成から表示、非表示に至るまで予測可能な一連の状態を経ます。理解することこれらのメソッドの順序と目的を理解することは、安定したiOSアプリの動作に不可欠です。

重要なポイント

  • ViewController Lifecycleは、UIKitが厳密な順序で呼び出す6つのUIViewControllerメソッドで構成されます
  • loadViewは、Storyboardを使用しない場合にView階層を作成します
  • viewDidLoadは1回だけ呼び出され、画面の初期設定に適しています
  • viewWillAppearviewDidAppearは表示のたびに発動します
  • viewWillDisappearviewDidDisappear — 状態の保存とクリーンアップ用

ViewController Lifecycleとは

ViewController Lifecycleとは、UIViewControllerがその存続期間中にUIKitから受け取るメソッドのセットです。iOSアプリの各画面は、作成、Viewのロード、画面表示、非表示、メモリ解放の段階を順番に経ます。UIKitは各段階で対応するメソッドを自動的に呼び出し、開発者は独自のロジックを追加するためにこれらをオーバーライドします。

UIViewControllerアーキテクチャはUIKitの基礎であり、SwiftUIの時代でも relevancy を保っています — 多くのプロジェクトは今でもクラシックなアプローチまたはハイブリッドアーキテクチャを使用しています。Lifecycleを理解することで、subviewsがいつ利用可能か、レイアウトを安全に変更できるタイミング、画面の表示時や非表示時にどの操作を実行すべきかを予測できます。

ライフサイクルの各メソッドには特定の目的があります: 一部はコントローラの全寿命を通じて1回だけ呼び出され、その他は表示または非表示のたびに呼び出されます。メソッド間でロジックを混在させると、メモリリーク、不正確なデータ更新、不要なネットワークリクエストなどの見つけにくいバグにつながります。

UIViewControllerメソッドの完全なサイクル

6つのメソッドがUIViewControllerの完全なライフサイクルを形成します。呼び出し順序は固定されており、ナビゲーション方法(push、present、unwind segue)に依存しません — すべて同じスケジュールに従います。

loadView — ルートViewの作成

loadViewはサイクルの最初のメソッドで、コントローラのViewがまだ存在しない場合に呼び出されます。Storyboardを使用する場合、UIKitは自動的にxibファイルからViewをロードします。プログラムでインターフェースを作成する場合、このメソッドをオーバーライドしてルートViewを手動で割り当てます。ほとんどのプロジェクトではloadViewは触らず、viewDidLoadで作業を行います。

loadViewのオーバーライドは特定の場合にのみ必要です: インターフェース全体をStoryboardなしでコードで作成する場合、またはルートViewが非標準クラスである必要がある場合です。Appleはオーバーライド時にsuper.loadViewを呼び出さないことを推奨しています — View作成の全責任を自分で負うことになります。

swift
override func loadView() {
    view = UIView()
    view.backgroundColor = .white
}

viewDidLoad — 一度きりの初期化

viewDidLoadはサイクルで最もよく使用されるメソッドです。Viewがメモリにロードされた後、まだ画面に表示されていない状態で1回呼び出されます。ここではsubviewsの設定、テーブルへのデータ入力、セルの登録、コントローラの全寿命にわたる通知のサブスクライブを行います。

重要な特徴: 画面が再表示されてもviewDidLoadは再度呼び出されません。画面が表示されるたびにデータを更新する必要がある場合は、viewWillAppearを使用してください。viewDidLoadには、基本設定に必要な1回限りの操作のみを配置します。

viewWillAppear — 表示前の準備

viewWillAppearは、Viewがユーザーに表示される直前に毎回呼び出されます。このメソッドは、表示がアニメーション化されているかどうかを示すanimatedパラメータを受け取ります。ここではデータの更新、テーブルのリロード、NavigationBarの設定、アプリケーションの状態に応じた要素の表示/非表示を行います。

画面間の状態同期にはviewWillAppearを使用します: ユーザーが前の画面でデータを変更した可能性がある場合、このメソッドがインターフェースを更新する適切な場所です。viewWillAppearの各呼び出しは、子コントローラから戻る場合でも、画面表示に先行します。

viewDidAppear — 画面が完全に表示された

viewDidAppearは、Viewが画面に完全に表示され、すべての遷移アニメーションが完了したことを通知します。この時点で、画面はインタラクションの準備が整い、ユーザーは完全なインターフェースを見て操作できます。このメソッドは、表示後に開始するアニメーションの開始、タイマーの開始、分析インプレッションの追跡に適しています。

viewWillAppearとは異なり、viewDidAppearは画面が表示されているだけでなく完全にレンダリングされていることを保証します。viewWillAppearでアニメーションを開始すると、UIKitがまだ遷移を完了していないため、一部のフレームがスキップされる可能性があります。スムーズなアニメーションにはviewDidAppearを使用してください。

viewWillDisappear — 非表示の準備

viewWillDisappearは、Viewが画面から消える前に呼び出されます — 別のコントローラへの遷移、モーダルウィンドウの閉じる、アプリの一時停止時などです。ここは状態の保存、通知のサブスクリプション解除、アクティブなプロセスの停止、画面が表示されていないときに不要なリソースの解放に適切な場所です。

重要: viewWillDisappearはViewが最終的に消えることを保証しません — ジェスチャーがキャンセルされる可能性があります。したがって、実際に非表示になった後にのみ呼び出されるviewDidDisappearでも重要なデータを保存してください。

viewDidDisappear — 画面が非表示

viewDidDisappearは表示と非表示のサイクルを完了します。Viewが画面から非表示になった後に呼び出されます。このメソッドでは、アニメーションを最終的に停止し、一時オブジェクトを削除し、viewWillDisappearで開始したデータ保存を確定します。

このメソッドはコントローラのdeinitにも先行します — UIViewControllerが破棄される場合、viewDidDisappearはdeinitが呼び出される前の最後のLifecycleメソッドになります。オブジェクトが破棄される前の最終クリーンアップに使用してください。

各メソッドが呼び出されるタイミング

呼び出しの順序は、画面が最初に表示されるか、戻るときか、モーダル表示されるかによって異なります。UIKitの観点から3つの主要なシナリオを見てみましょう。

最初の表示時の順序

画面が最初に表示される時、UIKitは完全な作成サイクルを経ます: loadViewが呼び出され、次にviewDidLoad、その後表示アニメーションが開始されます。アニメーション中にviewWillAppearが呼び出され、完了後にviewDidAppearが呼び出されます。これがloadViewからviewDidAppearまでのすべてのメソッドが順次発動する唯一のシナリオです。

swift
override func viewDidLoad() {
    super.viewDidLoad()
    print("viewDidLoad — Viewがメモリにロードされました")
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    print("viewWillAppear — まもなく表示されます")
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    print("viewDidAppear — 画面が完全に表示されました")
}

戻る時の順序

ユーザーが前の画面に戻る時、UIKitはviewDidLoadを再度呼び出しません — Viewは既にメモリにロードされています。代わりに、戻る画面ではviewWillAppearとviewDidAppearのみが呼び出され、現在の画面ではviewWillDisappearとviewDidDisappearが呼び出されます。loadViewとviewDidLoadは、画面が既にナビゲーションスタックに存在するためスキップされます。

PresentとDismissの特殊ケース

モーダル表示も同じルールに従います: 新しいコントローラは最初の表示時に完全なサイクルを経ますが、現在のコントローラはviewWillDisappearとviewDidDisappearを受け取ります。Dismiss時は順序が逆になります: 戻るコントローラは再びviewWillAppearとviewDidAppearを取得し、破棄されるコントローラは最終メソッドを受け取ります。この動作はUIKitのすべての遷移タイプで統一されています。

実用的な使用シナリオ

Lifecycleの理解がコード品質とユーザーエクスペリエンスに直接影響する4つの主要なシナリオを見てみましょう。各シナリオについて、推奨事項と共に例を提供します。

viewDidLoadでのデータ初期化

viewDidLoadは、画面の表示状態に依存しない初期設定の場所です。ここではcollectionViewの設定、セルのnibファイルの登録、データソースとレイアウトの作成を行います。ネットワークからデータをロードする場合、viewDidLoadではリクエストを開始するだけにして、画面が表示可能になったviewWillAppearでUIを更新するのが良い方法です。

swift
override func viewDidLoad() {
    super.viewDidLoad()
    tableView.register(
        MyCell.self,
        forCellReuseIdentifier: MyCell.identifier
    )
    viewModel.loadInitialData()
}

viewWillAppearでのコンテンツ更新

画面が表示されるたびのデータ同期にはviewWillAppearを使用します。例えば、ユーザーが前の画面で設定を変更した可能性がある場合、ここで表示値を更新し、テーブルをリロードし、NavigationBarの状態を調整します。これにより、あらゆるナビゲーションシナリオで画面が常に最新データを表示することが保証されます。

swift
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    tableView.reloadData()
    navigationController?.setNavigationBarHidden(false, animated: animated)
}

viewDidAppearでの分析とアニメーション

viewDidAppearは、ユーザーが画面を見た後に開始すべきアニメーションの開始に最適です。ここでは分析イベント(画面表示、オンボーディング開始、動画再生開始など)も送信します。遷移が完了する前にアニメーションを開始すると、カクつくインターフェースになります — UIKitが十分なフレーム数を準備する時間がありません。

viewWillDisappearでの状態保存

viewWillDisappearでは、ドラフトの保存、タイマーの停止、NotificationCenterからのサブスクリプション解除を行います。これは画面がまだ表示されており、ユーザーコンテキストを必要とする操作にアクセスできる最後の瞬間です。重要なデータについては、キャンセルされたジェスチャーに対する保護として、追加でviewDidDisappearも使用してください。

Lifecycle使用時の一般的な間違い

ライフサイクルメソッドの誤った使用は、iOSアプリのバグの最も一般的な原因の1つです。UIViewControllerを扱う様々な段階で開発者が犯す主な間違いを見てみましょう。

最初の間違い — Storyboard使用時にinitまたはloadViewでsubviewsを作成すること。Interface Builderを使用している場合、不必要にloadViewをオーバーライドしないでください。Storyboardが存在する状態でloadViewでViewを作成すると、xibファイルが無視され、空の画面になります。

2つ目の間違い — viewDidLoadでキーボード通知をサブスクライブしながら、サブスクリプション解除を行わないこと。UIResponder.keyboardWillShowNotificationにサブスクライブしたが、画面非表示時にサブスクリプションを解除しなかった場合、コントローラのdeinit後もブロックが呼び出され続けます — これはメモリリークであり、アプリがクラッシュする可能性があります。

3つ目の間違い — 画面が表示される前にタイマーやネットワークリクエストを開始すること。Viewがまだ表示されていない時に画像をロードしたりアニメーションを実行したりするのはリソースの無駄です。視覚的な更新はviewWillAppearまたはviewDidAppearに移動してください。

4つ目の間違い — viewWillDisappearのみでデータを保存すること。インタラクティブポップジェスチャーでは、ユーザーがスワイプを開始してキャンセルする可能性があります — メソッドは呼び出されましたが、画面は非表示になりませんでした。重要な保存はviewDidDisappearまたはapplicationDidEnterBackgroundハンドラでも重複して行ってください。

よくある質問

コントローラの存続期間中、viewDidLoadは何回呼び出されますか?

1回 — Viewがメモリにロードされた後です。画面が再表示されても、viewDidLoadは呼び出されません。Viewを再作成する必要がある場合、コントローラは破棄されて再作成される必要があります。

viewDidLoadでsuperを呼び出さないとどうなりますか?

ライフサイクルが正しく機能するためには、UIKitはsuper.viewDidLoadの呼び出しを必要とします。これがないと、レイアウトの更新や遷移の処理に問題が発生する可能性があります。メソッド内では常に最初にsuperを呼び出してください。

StoryboardとプログラムによるloadViewを同時に使用できますか?

推奨されません。コントローラがStoryboardから初期化された場合、UIKitは自動的にxibからViewをロードします。loadViewをオーバーライドするとこのプロセスがキャンセルされ、ストーリーボードは無視されます。

NotificationCenterから正しくサブスクリプションを解除するには?

viewDidLoadまたはviewWillAppearでサブスクライブし、viewWillDisappearまたはviewDidDisappearでサブスクリプションを解除します。クロージャでのメモリリークを防ぐために、selfへの弱参照を使用してください。

force quit時にviewDidDisappearが呼び出されないのはなぜですか?

Force quitはプロセスを強制終了するため、UIKitがLifecycleメソッドを呼び出す時間がありません。データを保存するには、AppDelegateでUIApplication.willTerminateNotificationを使用してください。

まとめ

  • ViewController Lifecycleは、UIKitが固定の順序で呼び出す6つのメソッドで構成されます
  • loadViewviewDidLoadはコントローラ作成時に1回発動します
  • viewWillAppearviewDidAppearは画面表示のたびに呼び出されます
  • viewWillDisappearviewDidDisappear — 非表示のたびに
  • 各メソッドには特定の目的があります — ロジックの混在はバグにつながります
  • 通知のサブスクリプションは、対応するメソッドでのサブスクリプション解除と常にバランスを取る必要があります
  • アニメーションと分析にはviewDidAppearを、状態保存にはviewWillDisappearを使用してください

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください