viewDidAppear は UIViewController のメソッドで、画面がディスプレイに完全に表示され、すべてのトランジションアニメーションが終了した後に UIKit が呼び出すものです。Apple Developer Documentationによると、このメソッドは View がユーザーに見えており、インタラクションの準備ができていることを保証します。viewDidAppear は、アニメーション、トラッキング、非同期オペレーションを開始するのに最適な場所です。
ポイント
viewDidAppear は UIViewController のメソッドで、View がウインドウ階層に追加され、トランジションアニメーションが完全に終了した後に UIKit が呼び出すものです。この時点で、画面は最終状態にあります:見えており、相互作用可能で、すべての UIKit アニメーションが停止しています。ディベロッパーは、画面がユーザーの矮にあることが保証されている必要があるアクションを実行するために、このメソッドをオーバライドします。
viewWillAppear が画面を表示する準備のみをしているのに対して、viewDidAppear は ユーザーがすでにインターフェースを見ていることを知らせます。これは重要な違いです:viewWillAppear でアニメーションを開始すると、UIKit がまだトランジションを処理しているため、フレームドロップが発生する可能性があります。viewDidAppear では、トランジションが完了しており、コントローラのリソースを新しいコンテンツのレンダリングに使用できます。
このメソッドは、viewWillAppear と同じく Bool タイプの animated パラメーターを受け取ります。true の場合、画面の表示にアニメーションが伴っていたことを示します。このパラメーターを使用して UI の動作を適応させることができます:例えば、非アニメーションの戻りでは入りアニメーションをスキップするなど。
viewDidAppear は、画面が表示プロセスを完了したすべてのシナリオで呼び出されます。iOS ディベロッパーの観点から主なケースを見てみましょう。
UINavigationController が push または pop アニメーションを終了した後、ターゲットコントローラで viewDidAppear が呼ばれます。スタックの最初の画面の場合、初期の開きアニメーション後に実行されます。これが 主なシナリオであり、ディベロッパーが viewDidAppear にロジックを配置する際に主に対象とするものです。
ユーザーがモーダル表示されたコントローラを閉じて前のコントローラに戻ると、UIKit は戻ってきたコントローラで viewDidAppear を呼びます。animated パラメーターは、dismiss がアニメーションを伴って実行されたかどうかに対応します。この瞬間は、チャイルド画面からデータを受け取った後に UI を更新するために重要です。
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
logScreenView()
startOnboardingAnimation()
}
UITabBarController は、切り替えアニメーションが完了した後に、選択されたタブのコントローラで viewDidAppear を呼びます。これは、切り替え開始時に実行される viewWillAppear とは異なります。タブにウェルカムアニメーションがあったり、アクティブ時間を追跡する必要がある場合、viewDidAppear が適切な場所です。
アプリがバックグラウンドからフォアグラウンドに戻る际、View のライフサイクルが一時的に中断されていた場合、可視コントローラで viewWillAppear と viewDidAppear が呼ばれることがあります。ただし、バックグラウンドからの戻りを確実に追跡するには、別途 UIApplication.willEnterForegroundNotification を使用してください。
viewDidAppear は、正しい実行に可視画面を必要とする任務を扱います。実際のプロジェクトでの主な使用シナリオを見てみましょう。
viewDidAppear の最も一般的な任務は、画面ビューの トラッキングです。Firebase Analytics、Amplitude、Mixpanel などのアナリティクスシステムは、画面が実際にユーザーに表示された後にのみイベントを受信する必要があります。viewWillAppear でイベントを送信すると、表示時間を低く評価し、誤った発火を生じる可能性があります。
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
Analytics.logEvent(
name: "screen_view",
parameters: [
"screen_name": "ProfileScreen",
"screen_class": String(describing: self)
]
)
}
画面が表示された後に開始すべきアニメーション——要素の段階的な表示、パララックス、チュートリアル——は viewDidAppear で開始されます。この時点で、グラフィックスコンテキストが完全に準備されており、アニメーションは開始時にフレームドロップなくスムーズです。これは、UIViewPropertyAnimator を使用するアニメーションに特に重要です。
軽い非同期オペレーション——高解像度画像のロード、大きな JSON の解析、動画の初期化——は、viewDidLoad や viewWillAppear よりも viewDidAppear で開始するほうが良いでしょう。メソッドが呼ばれるころでは、ユーザーはすでにインターフェースを見ているため、画面の表示を遅らせずにスケルトンやローダーを表示できます。
画面に定期更新が必要な要素がある場合——カウントダウンタイマー、進行指示器、進行アニメーション——それらは viewDidAppear で開始され、viewDidDisappear で停止されます。これにより、画面が見えないときに タイマーが動作するのを防ぎ、バッテリーと CPU リソースを節約します。
メディアコンテンツ——動画、音声、Lottie アニメーション——は、それより前ではなく、viewDidAppear で開始されます。viewWillAppear で再生を開始すると、画面がまだ表示されている間にユーザーが最初の数秒間を逃す可能性があります。viewDidAppear では、ユーザーが最初のフレームからコンテンツを見ていることを確信して AVPlayer や Lottie アニメーションを開始できます。これは、オンボーディング画面やスプラッシュ画面など、精確なタイミングが重要な場合に特に重要です。
アニメーションを開始する 正しいタイミングは、インターフェースの滑らかさの知覚に直接影響します。単純なアニメーションでは viewWillAppear と viewDidAppear での違いは目立たないかもしれませんが、複雑なシーンでは重要になります。
UIKit が画面間で push トランジションを実行するとき、スクリーンショットを取得してアニメートし、同時に新しいコントローラで viewWillAppear を呼びます。この瞬間に 軽いアニメーション——パララックス、ブラー、変換——を開始すると、UIKit がトランジションアニメーションのフレームをドロップし、ガタガタシた効果を生じる可能性があります。viewDidAppear は、トランジションアニメーションが完了していることを保証し、レンダリングを完全に制御できます。
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(
withDuration: 0.6,
delay: 0.3,
usingSpringWithDamping: 0.8,
initialSpringVelocity: 0.5
) {
self.cardView.alpha = 1.0
self.cardView.transform = .identity
}
}
要素の自然なカスケード表示を作り出すために 遅延とダンピングを使用します。このアプローチにより、インターフェースの知覚が向上し、 dwell time が増加します——ユーザーはコンテンツの探索により多くの時間を費やし、行動メトリクスに良好な影響を与えます。
不正な使用 viewDidAppear は、パフォーマンス問題、アニメーションの予期せぬ動作、トラッキングの過剰を引き起こす可能性があります。よくある資いを見てみましょう。
1つ目の資いは、複数回の呼び出しです。viewDidAppear は、タブ切り替え、バックグラウンドからの戻り、モーダルトランジションなどの特定のシナリオで複数回呼ばれることがあります。メソッドがフラグの確認なく軽い処理を実行する場合、それは複製されます。単回のアクションには hasAppeared フラグまたは dispatchOnce を使用します。
2つ目の資いは、非表示時にキャンセルせずにネットワークリクエストを開始することです。リクエストが完了する前にユーザーが画面を退すると、結果がすでに非表示の View に適用される可能性があります。キャンセル可能な URLSessionTaskを使用し、viewDidDisappear でキャンセルします。
3つ目の資いは、viewDidAppear の代わりに viewWillAppear でトラッキングすることです。いくつかのディベロッパーは viewWillAppear でアナリティクスイベントを送信しますが、画面が表示されなかった場合(例:キャンセルされた pop ジェスチャー)、誤った発火が生じます。viewDidAppear は、ユーザーが実際に画面を見たことを示す唯一の信頼できる指標です。
4つ目の資いは、super を忘れることです。super.viewDidAppear の呼び出しは、UINavigationController、UITabBarController、UISplitViewController の正常動作に必要です。これがないと、標準のナビゲーションおよびインターフェース更新メカニズムが 壊れる可能性があります。
5つ目の資いは、viewDidLayoutSubviews を考慮せずにオリエンテーションや画面サイズを変更することです。viewDidAppear でのアニメーションが View の最終サイズに依存する場合、viewDidLayoutSubviews が viewDidAppear より前に複数回呼ばれる可能性があることを記憶してください。最初の画面表示時には、viewDidAppear が呼ばれる前にレイアウトが完了しますが、その後のサイズ変更時(例:デバイスの回転)には viewDidAppear が呼ばれず、アニメーションが開始されない可能性があります。こうした場合は、firstLayout フラグの確認を伴う viewDidLayoutSubviews を使用してください。
正しい実装では、アニメーションオブジェクトへの参照を保持し、画面を退する際に明示的にキャンセルする必要があります。6つ目の資いは、停止フラグなしで無限アニメーションを開始することです。viewDidAppear で繰り返しアニメーション(例:ぱルスする指示器や回転ローダー)を開始しても、viewDidDisappear で停止しない場合、画面が非表示でもアニメーションが GPU リソースを消費し続けます。常にアクティブなアニメーションへの参照を保持し、対応するライフサイクルメソッドで removeAllAnimations または setCompletion を呼び出します。
7つ目の資いは、アクティビティを停止するために viewDidDisappear を無視することです。viewDidAppear で GPS、加速度センサー、ジャイロスコープのリスニングを開始した場合、viewDidDisappear で必ず停止します。さもなければ、ユーザーが既に別の画面に移動していても、センサーがバックグラウンドで動作し続け、バッテリーを消費します。対応するライフサイクルメソッドで、組み合わせた開始・停止呼び出しを使用してください——これにより、デバイスのリソースを正しく管理できます。
よくある質問
viewWillAppear は、画面がまだ見えない表示アニメーションの前に呼ばれます。viewDidAppear は、アニメーションが完全に終了し、画面が見えて相互作用可能になった後に呼ばれます。
viewDidAppear では、UIKit の トランジションアニメーションがすでに終了し、すべてのレンダリングリソースがコントローラに利用可能です。これより前にアニメーションを開始すると、フレームドロップが発生し、ガタガタしたインターフェースになる可能性があります。
通常のライフサイクルでは、いいえ——viewDidAppear は常に viewWillAppear の後に呼ばれます。ただし、状態復元の特定のシナリオでは、システムが viewDidAppear のみを呼ぶ場合があります。
firstAppearance の フラグ確認を追加するか、カウンターと画面名の組み合わせを使用します。例えば、firstAppearance = true の場合にのみ screen_view イベントを送信し、その後フラグをリセットします。
バックグラウンドから戻る際、View がメモリからアンロードされていた場合、UIKit が可視コントローラで viewDidAppear を呼ぶことがあります。信頼できる追跡には、AppDelegate の通知を使用してください。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。