はじめに
ビューコントローラーの階層構造を追う際にデバッグとしてログ出力したい場面があったので、忘備録として記載します。
コード解説
以下のメソッドをターゲットクラス内の適当な場所に定義します。
func logCurrentViewControllerHierarchy() {
print("現在のビューコントローラー階層:")
// ナビゲーションスタックのログ
if let navigationController = self.navigationController {
print("ナビゲーションスタックのビューコントローラー一覧:")
for (index, viewController) in navigationController.viewControllers.enumerated() {
print("Index \(index): \(String(describing: type(of: viewController)))")
}
} else {
print("ナビゲーションコントローラーが見つかりません。")
}
// モーダルプレゼンテーションチェーンのログ
var currentVC: UIViewController? = self
print("モーダルプレゼンテーションチェーンのビューコントローラー一覧:")
while let presentingVC = currentVC?.presentingViewController {
print("\(String(describing: type(of: presentingVC)))")
currentVC = presentingVC
}
}
各要素の解説
navigationController
現在のビューコントローラーが所属するナビゲーションコントローラーを取得する。
viewControllers
ナビゲーションスタックに含まれるビューコントローラーを配列で取得し、各ビューコントローラーのクラス名をログに出力する。
presentingViewController:
現在のビューコントローラーがモーダルとして表示されている場合、その親ビューコントローラーを辿ってログに出力する。
使用例
画面ロード完了後
override func viewDidAppear() {
super.viewDidAppear()
// ビューコントローラーが表示されたときに階層をログに出力
logCurrentViewControllerHierarchy()
}
ボタンタップ時
@IBAction func someButtonTapped(_ sender: Any) {
// ボタンがタップされたときに階層をログに出力
logCurrentViewControllerHierarchy()
}
特定のイベント後(例:画面遷移時)
func transitionToNextScreen() {
// 次の画面に遷移する
let nextViewController = NextViewController()
self.navigationController?.pushViewController(nextViewController, animated: true)
// 遷移後の階層を確認
logCurrentViewControllerHierarchy()
}
出力結果例
SettingViewController がナビゲーションスタックに存在しているかつ、AlertControllerがモーダルで表示されている場合の出力例
現在のビューコントローラー階層:
ナビゲーションスタックのビューコントローラー一覧:
Index 0: ViewController
Index 1: SettingViewController
モーダルプレゼンテーションチェーンのビューコントローラー一覧:
AlertController
活用できそうなシーン例
・モーダルが正しく表示されない場合
・意図しないビューコントローラーがスタックに追加されている場合
・インスタンスが正しく破棄されているか確認したい場合
・ナビゲーションとモーダル遷移が絡む複雑なシナリオの場合
まとめ
今回紹介した方法を使えば、ビューコントローラーの階層がどんな状態かを簡単に把握できるようになります。画面遷移がうまくいかないときや、意図しない動作が発生したときに、ぜひこのコードを活用してみてください。
※デバッグ完了後はログの出力処理を削除するか、必要に応じて開発環境でのみ実行されるようにすることを忘れないように!