Edited at

whose view is not in the window hierarchy! 初心者向け エラー解消


環境

iOS 12.0

Swift 5

Xcode 10.2


想定していた動作


ログイン画面を表示する時に、以前のログイン情報が残っていたら自動的に別の画面に遷移させる!

以下のコードだと、反応がなかった。。。

ログインしていたら、メッセージページに移動するようにしたかったです。


LoginViewController.swift

    override func viewDidLoad() {

super.viewDidLoad()
user.delegate = self
if user.isLogin() {
moveMessagePage()
}
}
(省略)
func moveMessagePage() {
let storyboard = UIStoryboard(name: "Message", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "MessageStoryboard")
self.present(viewController, animated: true, completion: nil)
}



User.swift

  // ログインしているかどうか

func isLogin () -> Bool {
if user != nil {
return true
}
return false
}


whose view is not in the window hierarchy! のエラーがコンソールに発生していた

なんでだろう?と思ってデバックしていたらコンソールに上記のエラーが記述してあった。

直訳すると、「そのビューはウィンドウ階層にはありません。」 らしい。

なるほど。まだviewが出来上がってないのに、移動なんてできるわけないだろ!ってことか。

viewDidLoad() だから、viewのロードだけ終わっている状態で、viewは作成されてないもんな。

わかりやすい画像+説明がこの記事に載っていた!

UIViewControllerのライフサイクル

以下の画像は引用です。

スクリーンショット 2019-04-06 10.56.54.png

実行される順番が記述されてますね。

わかりやすい!

つまり、viewDidApperにさっきのロジックを記述すると、エラーが出ずに実行されるのか!

ちなみに、viewWillApperにロジック書いてもダメです。まだviewができてないからですね。

以下が、実行したら上手くいったコードです!

無事に、ログイン画面を表示する時に、自動的にメッセージ画面に遷移することができました!


LoginViewController

    override func viewDidLoad() {

super.viewDidLoad()
user.delegate = self
// Do any additional setup after loading the view.
}

override func viewDidAppear(_ animated: Bool) {
if user.isLogin() {
moveMessagePage()
}
}
(省略)
func moveMessagePage() {
let storyboard = UIStoryboard(name: "Message", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "MessageStoryboard")
self.present(viewController, animated: true, completion: nil)
}



参考

以下の記事を参考にさせていただきました。ありがとうございました。

@motokiee

UIViewControllerのライフサイクル

@Atsushi_

swift初心者:画面推移時の「whose view is not in the window hierarchy!」の対処方法

@shtnkgm

UIKitのView表示ライフサイクルを理解する