viewWillAppearは、画面がユーザーに表示される直前にUIKitが毎回呼び出すUIViewControllerメソッドです。Apple Developer Documentationによると、このメソッドはブールパラメータanimatedを受け取り、トランジションがアニメーション付きで発生するかどうかを示します。viewWillAppearは、データの更新と画面状態の同期を行う主要な場所です。
重要なポイント
viewWillAppearは、UIKitがViewをウィンドウ階層に追加する直前に呼び出すUIViewControllerメソッドです。この時点で、ViewはAuto Layoutパスを経て最終的な寸法を持っていますが、まだユーザーには見えません—トランジションアニメーションがまだ開始されていないか、進行中です。開発者はこのメソッドをオーバーライドして、画面が表示されるたびに実行する必要がある操作を行います。
一度だけトリガーされるviewDidLoadとは異なり、viewWillAppearは画面が表示されようとするたびに呼び出されます:初期表示時、子コントローラーからの戻り時、モーダルウィンドウを閉じた後、TabBarタブの切り替え時。これにより、インターフェースの状態を最新に保つための重要なメソッドとなっています。
このメソッドはBool型のanimatedパラメータを受け取ります。画面の表示にアニメーションが伴う場合はtrueになります。このパラメータは、NavigationBarやTabBarのメソッドに渡すのに便利です。これらのメソッドにも一貫した動作のための同様のパラメータがあります。
viewWillAppear呼び出しのタイミングはナビゲーションの種類によって異なりますが、一般的なルールは変わりません。メソッドはViewが表示される前にトリガーされます。主なシナリオを見てみましょう。
viewDidLoadの後、UIKitは表示の準備を開始します。Viewが階層に追加され、レイアウトパスがトリガーされ、トランジションアニメーションが始まる直前にviewWillAppearが呼び出されます。この時点では、画面はまだ表示されていませんが、すべてのサブビューのサイズは正しく、その内容を安全に更新できます。
ユーザーが戻るボタンをタップするか、プログラムでpopViewControllerを呼び出すと、UIKitは前の画面に戻り、そのviewWillAppearを呼び出します。これがviewWillAppearを使用する主要なシナリオです—項目追加後のリスト更新や設定の同期に使用します。
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
updateBadgeCount()
}
モーダル表示されたコントローラーを閉じた後、UIKitはそれを表示したコントローラーのviewWillAppearを呼び出します。このシナリオは、デリゲートやクロージャを使用してデータを返す場合に特に注意が必要です—viewWillAppearは結果を受け取った後に画面が更新されることを保証します。
TabBarControllerは、切り替えが発生するたびに選択されたタブのコントローラーのviewWillAppearを呼び出します。タブに動的データ(為替レート、通知、ユーザーステータスなど)が表示されている場合、viewWillAppearはそれらを更新する理想的な場所です。
viewWillAppearは、他のメソッドでは実行不可能または最適ではないいくつかの特定のタスクを解決します。主なものを見てみましょう。
viewWillAppearの最も一般的な使用法は、画面が表示されるたびにUITableViewまたはUICollectionViewをリロードすることです。前の画面でデータが変更された可能性がある場合(項目の追加、ステータスの変更)、viewWillAppearでreloadDataを呼び出すことで、ユーザーが最新の情報を確実に表示できます。
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
viewModel.synchronize()
tableView.reloadData()
}
viewWillAppearでは、NavigationBarの外観を簡単に設定できます:非表示/表示、色の変更、ラージタイトルの設定。異なる画面でNavigationBarのスタイルが異なる場合、viewDidLoadは一度しか呼び出されないため、viewWillAppearがこれらの変更を行う適切な場所です。
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(
false, animated: animated
)
navigationController?.navigationBar.prefersLargeTitles = true
tabBarController?.tabBar.isHidden = false
}
画面が表示されている間だけ意味を持つ通知(キーボード通知、コンテンツ変更通知)は、viewWillAppearで購読し、viewDidDisappearで購読解除します。これにより、画面がアクティブでない場合の不要なハンドラを防ぎ、メモリリークから保護します。
アプリによって画面が非表示にされたり最小化されたりする可能性がある場合、viewWillAppearはUI状態を復元するのに便利な場所です:セグメントの切り替え、スクロール位置の復元、一時的な変更のリセット。ユーザーは画面が表示されるたびに予測可能な状態で画面を取得できます。
未読メッセージ、評価、通知のカウンターを表示する画面では、viewWillAppearがそれらを更新する適切な場所です。ユーザーが別の画面で数量を変更した可能性がある場合、ここで再計算とUITabBarItem.badgeValueまたはカスタムインジケーターの更新が呼び出されます。これにより、ユーザーが他の画面にどれだけ長くいたかに関係なく、常に最新の数値が表示されます。
collectionViewの操作には特に注意が必要です:画面上のデータがカウンターやステータスを含むセルのグリッドとして表示される場合、viewWillAppearでの更新は選択的に行う必要があります。完全なreloadDataの代わりに、表示されているセルにはreloadItemsAtIndexPathsを使用して、ちらつきやスクロール位置の喪失を防ぎます。
viewWillAppearとviewDidLoadの違いを理解することは、適切なUIViewControllerアーキテクチャの基礎です。これらのメソッドは、呼び出し頻度、コンテキスト、目的が異なります。
viewDidLoadは一度だけ呼び出され、時間とともに変化しない設定に適しています:セルの登録、デリゲートの設定、定数の初期化。viewWillAppearは表示のたびに呼び出され、繰り返し必要な操作に適しています:データの更新、表示要素の設定、状態の同期。
| 特性 | viewDidLoad | viewWillAppear |
|---|---|---|
| 頻度 | 一度 | 表示のたびに |
| Viewの表示 | なし | なし(まもなく表示) |
| Viewの寸法 | 最終ではない | 最終 |
| 適している | 一度きりの設定 | 更新と同期 |
| アニメーション | 適用外 | animatedパラメータ |
黄金のルール:操作を一度だけ実行する必要がある場合はviewDidLoadに配置します。画面に戻るたびに実行する必要がある場合はviewWillAppearに配置します。
誤った使用法は、パフォーマンスの問題、過剰な更新、インターフェース状態の不整合を引き起こす可能性があります。最も一般的な間違いを見てみましょう。
最初の間違い—viewDidLoadのロジックの重複。viewDidLoadとviewWillAppearの両方でテーブルセルを登録すると、一度の設定で十分なにもかかわらず、登録が複数回実行されます。すべての一度きりの設定はviewDidLoadに移動してください。
2番目の間違い—毎回の表示での無条件のreloadData。データが変更されていない場合、テーブルのリロードはデータソースへの不要なクエリとセルの再描画を引き起こし、パフォーマンスを低下させます。reloadDataを呼び出す前に、状態が実際に変更されたかどうかを確認してください。
3番目の間違い—リクエストが完了する前に画面が再び非表示になる可能性を考慮せずにネットワークリクエストを処理すること。viewWillAppearでURLSessionリクエストを開始し、ユーザーがすぐに別の画面に移動した場合、結果が既に非表示のViewに適用される可能性があります。更新する前に、キャンセル可能なタスクを使用するか、isViewLoadedとwindowを確認してください。
4番目の間違い—superの呼び出し忘れ。super.viewWillAppearを呼び出さないと、親コントローラー(UINavigationController、UITabBarController)の動作が壊れ、ジェスチャーやトランジションの処理が不正になる可能性があります。superは常に呼び出す必要があります。
5番目の間違い—layoutIfNeededを呼び出さずに制約を変更すること。viewWillAppearでプログラムによって制約を変更すると、UIKitはそれらを即座に適用しません—変更は次のレイアウトパスまで蓄積されます。制約の変更後に変更を即座に適用するには、view.layoutIfNeeded()を呼び出してください。これは、コンテンツに依存する要素の高さを調整する場合に特に重要です。
6番目の間違い—viewWillAppearでアニメーションを実行しようとすること。前述のように、UIKitはまだトランジションアニメーションを処理しており、あなたのアニメーションはシステムのアニメーションと競合する可能性があります。要素をエフェクト付きで表示する必要がある場合は、viewDidAppearでインミングアニメーションを使用し、viewWillAppearでは初期状態のみを設定します:透明度0、スケール0.8のtransformなど。
7番目の間違い—animatedパラメータの無視。一部の開発者はviewWillAppearでanimatedの値をチェックせず、アニメーションの有無に依存すべき操作を実行します。例えば、animated = falseの場合はアニメーションなしでNavigationBarを非表示にでき、animated = trueの場合はアニメーション付きで非表示にして、トランジションをスムーズに見せることができます。常にanimatedパラメータを適切なUIKitメソッドに渡してください。
8番目の間違い—画面が表示されていないときのUIの変更。viewWillAppearでネットワークリクエストを開始し、そのcompletionブロックが画面が既に非表示になった後にUIを更新すると、ユーザーはちらつきや不整合な状態を目にします。クロージャでUIを更新する前に、常にisViewLoadedとwindowを確認してください。この簡単なアクションで、クラッシュや不要なインターフェースの再描画を防げます。
よくある質問
viewWillAppearは表示アニメーションが始まる前に呼び出され、Viewはまだ表示されていません。viewDidAppearはアニメーション完了後に呼び出され、画面が完全に表示され、インタラクションが可能になります。
通常の状態では、画面が表示されるときにviewWillAppearは常に呼び出されます。例外はアプリの強制終了で、UIKitがLifecycleメソッドを呼び出す時間がない場合です。
はい、必須です。UIKitはこの呼び出しをUINavigationControllerやUITabBarControllerとの内部調整に使用します。superがないと、ジェスチャーやトランジションアニメーションが壊れる可能性があります。
タブを切り替えるたびに。UIKitは、ユーザーがTabBarの対応するアイコンをタップした直後に、選択されたタブのコントローラーのviewWillAppearを呼び出します。
コントローラーのプロパティまたは共有データソースを使用します。popViewControllerを呼び出す前に、前のコントローラーに必要な値を設定すると、そのviewWillAppearですでに利用可能になります。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。