ViewControllerのライフサイクルについて


#はじめに
ViewControllerのライフサイクルとオーバーライド時の適切な処理を備忘録として書きます。

#ViewControllerのライフサイクル
以下のようになっており、上から順に呼ばれます。

```swift
① func loadView()
↓
② func viewDidLoad()
↓
③ func viewWillApper(_:)
↓
④ func viewWillLayoutSubviews(_:)
↓
⑤ func viewDidLayoutSubviews(_:)
↓
⑥ func viewDidAppear(_:)
↓
⑦ func viewWillDisappear(_:)
↓
⑧ func viewDidDisappear(_:)
```

##①loadView()
`viewを生成するメソッド`であり、`1度`だけ呼ばれます。

Storyboardやxibなど、`InterfaceBuilder`を使用している場合は
このメソッドを`オーバライドしてはいけません`。

[loadView() | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621454-loadview)

####・適切な処理
`コードでviewを作成する場合`などに適しています。
その際には、`super.loadView()`は呼びません。

##②viewDidLoad()
`viewがメモリに読み込まれた後`に`1度`だけ呼ばれます。

[viewDidLoad() | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621495-viewdidload)

####・適切な処理
`viewに対する追加の初期化処理`や`ネットワーク通信`など1度だけ行う何らかの処理などが適しています。

`基本的な初期化の処理`は大体ここで行いますが、このタイミングではviewの`frame`が確定されていないので`正確なframeを取得することが出来ません`。

`viewDidLayoutSubviews(_:)以降`にviewのサイズに関連した処理を書く必要があります。

##③viewWillAppear(_:)
`viewが画面に表示される直前`に呼ばれます。

`loadView()`や`viewDidLoad()`と違って
遷移やTab Bar切り替え時など`画面が表示されようとする度に`呼び出されます。

一方で`ホーム画面からの復帰`や、`コントロールセンターを閉じたりした時`には呼ばれません。

[viewWillAppear(_:) | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621510-viewwillappear)

####・適切な処理
`viewが画面に表示される前に実行する必要のある処理`や
`画面を表示するたびにviewを更新したい場合`などに適しています。

##④viewWillLayoutSubviews(_:)
`viewがSubviewをレイアウトする前`に呼ばれます。

デフォルト実装では`何もしません`。

[viewWillLayoutSubviews(_:) | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621437-viewwilllayoutsubviews)

##⑤viewDidLayoutSubviews(_:)
`viewがSubviewをレイアウトした後`に呼ばれ、デフォルト実装では`何もしません`。

`viewDidLoad()`の部分で書いたように
これ以降のタイミングではないと`正確なframeは取得できません`。

[viewDidLayoutSubviews(_:) | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621398-viewdidlayoutsubviews)

####・適切な処理
`viewのサイズに関係する処理`などが適しています。

##⑥viewDidApper(_:)
`viewが画面に表示された後`に呼ばれます。

このメソッドが呼ばれたタイミングでは、`すでにviewが描画されている状態`なので
ここで`viewの生成を行えば、おかしな事になったりするので注意が必要`です。

[viewDidAppear(_:) | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621423-viewdidappear)

####・適切な処理
`アニメーション開始、動画の再生`や`データのフェッチ`など
`viewが画面に表示された後、すぐに必要となる処理`を行うのに適しています。

##⑦viewWillDisappear(_:)
`viewが表示されなくなる直前`に呼ばれます。

具体的には、`画面遷移`や`Tab Barによる切り替え時`に呼ばれます。

[viewWillDisappear(_:) | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621485-viewwilldisappear)

##⑧viewDidDisappear(_:)
遷移などで`viewが完全に表示されなくなった時`に呼ばれます。

[viewDidDisappear(_:) | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621477-viewdiddisappear)

####・適切な処理
`何らかの終了処理`などをここで行うのに適しています。

#おわりに
`loadView()`や`viewDidLoad()`以外のメソッドはライフサイクルの中で複数回呼ばれるので、viewの追加や`重い処理`などには注意が必要です。

間違っていればコメントして下さると有り難いです！

#参考資料
[ViewControllerのライフサイクル](https://medium.com/@shiba1014/viewcontroller%E3%81%AE%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AB-37151427bda5)
[iOS開発におけるUIViewControllerのライフサイクルイベントまとめ](https://stalte.hatenablog.com/entry/2018/08/03/102040)