てくてくテック

気ままに開発のメモを書いていこうと思います。主にSwiftかと。

ViewDidLayoutがいつ呼ばれるのか知りたい

みなさんこんにちはtakenoteです。 この二日三日で突然暖かくなって、家から出た時に幸せを感じるようになってきました。

朝明るくなるまでの時間も徐々に早くなってきて、冬の終わりを肌で感じます。良いですよね、春。花粉がなければ。

今日のお話

StoryBoard上で入れ子構造のレイアウトを作った時、どれがどの順番で呼ばれるのかを調べてみました

前提

僕が今作っているレイアウトはこんな感じです。

f:id:takenote-y:20180304153326p:plain

ViewController AはStoryBoard上に直接CustomViewを配置しています。 ViewController BはGameViewControllerのViewDidLoad上でViewControllerCを中味に実装します。 (ほんとは他にも細かいUIPartsがありますが、ここでは簡略化のため記載を省略しています)

絵で示すとこんな感じです。

f:id:takenote-y:20180304152958p:plain

結論

呼ばれるのは以下のような順番でした。

1. GameViewControllerのinit

1.1. ViewControllerAのinit

  - 1.1.1. CustomViewのxibファイルからの生成

1.2. ViewControllerAのviewDidLoad()

1.3. ViewControllerBのinitとviewDidLoad()

2. GameViewControllerのviewDidLoad()

2.1. ViewControllerCのinit

   - 2.1.1. CustomViewのxibファイルからの生成

2.2. ViewControllerCのviewDidLoad()

3. GameViewControllerのViewDidLayoutSubViews()

3.1 ViewControllerBのViewDidLayoutSubViews()

3.2 ViewControllerBのViewDidLayoutSubViews()

詳細

今回整理してみて、大切だと思ったのは以下の二つだと考えています。

 1. UIViewControllerのviewDidLoadはUIViewControllerのインスタンスが生成された後に呼ばれる

 2. もしそのViewControllerが内部にViewを持つ場合は、自身のインスタンスを生成する過程でその子Viewを生成する

こうして記事をまとめていると至極当たり前のことを書いているような気がしてしまいます。 なんで view did loadな関数なわけですから、自分の持っているviewは全てLoadされているわけですよね、 なので呼び出されている順番自体は大きい枠から順番なのですが、 実際に完了していく順番(viewDidLoad()が呼ばれる順番)は中に入っている子Viewからになるわけなんですね。納得したなぁ。

終わりに

この順番を把握していなかったおかげで、Viewをアップデートしたはずなのに毎回初期化されてしまって大変な目にあってしまいました。 初期化のmethodをどこに入れるべきか、とかこの数値を参照するためにはこういう順番だからここできちんと定義しておかなきゃ、とか、呼ばれている順番をきちんと理解するのは非常に大切なことだなーと実感しました。 次回はこの順番を把握するために調べたdebugの方法、効率のよいLog出力についてまとめられれば良いなと考えています。