はじめに
UIKitでモーダル画面を表示する際、ローディングインジケーター(PKHUD)が表示されない問題に遭遇しました。本記事では、その原因と解決方法について解説します。
事象
- モーダル画面表示時にPKHUD(https://github.com/pkluz/PKHUD)が表示されない
- UIKitの
ViewController.viewDidLoad()のタイミングでAPIを呼びたい - API呼び出し中は画面操作を受け付けないためPKHUDを画面に表示したいが表示されない
原因
PKHUDは自身のUIViewに対してaddSubViewを行うため、モーダル画面のviewDidLoad()ではウィンドウ階層が確定していません。そのため、PKHUDが正しく表示されないという問題が発生します。
viewDidLoad()はビューがメモリにロードされた直後に呼ばれますが、この時点ではビューはまだウィンドウ階層に追加されていません。PKHUDのようなオーバーレイ表示を行うライブラリは、ビューが画面に表示されている状態でないと正常に動作しないことがあります。
解決方法
viewDidAppear()のタイミングでAPI呼び出しとPKHUDの表示を行うことで問題を解決できます。
修正前のコード
override func viewDidLoad() {
super.viewDidLoad()
// PKHUDを表示
HUD.show(.progress)
// API呼び出し
fetchData()
}
修正後のコード
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// PKHUDを表示
HUD.show(.progress)
// API呼び出し
fetchData()
}
private func fetchData() {
// API処理
APIClient.fetch { [weak self] result in
// 処理完了後にHUDを非表示
HUD.hide()
switch result {
case .success(let data):
// データ処理
break
case .failure(let error):
// エラー処理
break
}
}
}
なぜviewDidAppear()で解決するのか
viewDidAppear()は、ビューが画面に表示された直後に呼ばれるライフサイクルメソッドです。この時点ではビューは完全にウィンドウ階層に組み込まれており、PKHUDのようなオーバーレイ表示が正常に動作します。
注意点
-
viewDidAppear()は画面が表示されるたびに呼ばれるため、一度だけ実行したい処理の場合はフラグ管理が必要です - 画面遷移のアニメーションが完了してから処理が始まるため、若干のタイムラグが発生する可能性があります
- ユーザー体験を考慮して、必要に応じて別の方法(例:遷移前の画面でローディングを開始)も検討してください
まとめ
モーダル画面でPKHUDが表示されない場合は、ビューのライフサイクルを見直すことで解決できます。viewDidLoad()ではなくviewDidAppear()でPKHUDの表示とAPI呼び出しを行うことで、正常に動作するようになります。
同様の問題は他のオーバーレイ表示ライブラリでも発生する可能性があるため、ビューのライフサイクルを理解しておくことが重要です。