小さなViewControllerで画面を組み立てる

ViewではなくViewControllerで画面部品を細かく分けて画面を組み立てるサンプルです。
下にToolbarがあり、それ以外はWebViewという簡単な画面です。

簡単な内容ですが、2つ[罠に嵌ってしまった](https://qiita.com/drafts/ed12d2ce81ee20d43261#注意点)ため、誰かの助けになることを期待して情報を残しておきます。

<img width="200" alt="WebViewとToolbarの画面" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27407/68d0bba6-1c19-7bcb-7455-40fd90be15ad.png">


## WebViewController

画面表示以外のコードがありません。
外からURLを指定して読み込む機能などは、必要な場合各自追加をお願いします🙇‍♂️

```WebViewController.swift
import UIKit
import WebKit

class WebViewController: UIViewController {

    var webView: WKWebView!

    override func loadView() {
        let configuration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: configuration)
        view = webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        let url = URL(string: "https://google.com")!
        let request = URLRequest(url: url)
        webView.load(request)
    }
    
}
```

## ToolbarViewController

こちらも画面表示以外のコードがありません。

```ToolbarViewController.swift
import UIKit

class ToolbarViewController: UIViewController {

    var toolbar: UIToolbar!

    override func loadView() {
        toolbar = UIToolbar(frame: .zero)
        let back = UIBarButtonItem(title: "back", style: .plain, target: nil, action: nil)
        toolbar.items = [back]
        view = toolbar
    }
}
```

## 画面を組み立てる

```
import UIKit

class ViewController: UIViewController {

    let toolbar = ToolbarViewController()
    let webView = WebViewController()

    override func loadView() {
        view = UIView(frame: .zero)

        webView.view.translatesAutoresizingMaskIntoConstraints = false
        addChild(webView)
        view.addSubview(webView.view)
        webView.didMove(toParent: self)

        toolbar.view.translatesAutoresizingMaskIntoConstraints = false
        addChild(toolbar)
        view.addSubview(toolbar.view)
        toolbar.didMove(toParent: self)

        let guide = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            webView.view.topAnchor.constraint(equalTo: view.topAnchor),
            webView.view.leftAnchor.constraint(equalTo: view.leftAnchor),
            webView.view.bottomAnchor.constraint(equalTo: toolbar.view.topAnchor),
            webView.view.rightAnchor.constraint(equalTo: view.rightAnchor),
            toolbar.view.leftAnchor.constraint(equalTo: view.leftAnchor),
            toolbar.view.bottomAnchor.constraint(equalTo: guide.bottomAnchor),
            toolbar.view.rightAnchor.constraint(equalTo: view.rightAnchor)
            ])
    }

}
```

あまり難しい箇所もなくできました！

小さなViewControllerは、Viewが1個ならAutoLayoutのコードを書く必要もないです。
2,3個に押さえて入れ子にすれば、AutoLayoutのコードは短くわかりやすい範囲に収まります。

そのためxibを使わなくても書きやすくなる場合が多いです。
（逆にVCの数だけxibが増殖すると、管理がちょっと面倒かも）

# 注意点

## viewに直接UIToolbarを設定すること

`var UIViewController.view` に直接UIToolbarを設定してください。
以下のようにUIViewの中にUIToolbarを`addSubview`してはいけません。

```swift
    override func loadView() {
        view = UIView(frame: .zero)

        toolbar = UIToolbar(frame: .zero)
        toolbar.translatesAutoresizingMaskIntoConstraints = false
        let back = UIBarButtonItem(title: "back", style: .plain, target: nil, action: nil)
        toolbar.items = [back]
        view.addSubview(toolbar)

        NSLayoutConstraint.activate([
            toolbar.topAnchor.constraint(equalTo: view.topAnchor),
            toolbar.leftAnchor.constraint(equalTo: view.leftAnchor),
            toolbar.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            toolbar.rightAnchor.constraint(equalTo: view.rightAnchor)
            ])
    }
```

UIViewの中のUIToolbarを入れる構成では **ToolbarのSafe Area対応が機能しません！**
以下のような表示になってしまいます。

<img width="200" alt="Safe Areaが想定どおり動いてくれない" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27407/73185e39-382d-b754-d072-bff6afc4c656.png">


## UIViewControllerの中で `self.view.translatesAutoresizingMaskIntoConstraints = false` しない

上記サンプルの例であれば、WebViewControllerの`loadView()`で
`self.view.translatesAutoresizingMaskIntoConstraints = false`
しても期待通りに動作します。

しかしそれをした場合 **WebViewControllerをモーダル表示すると正しく表示されません！**
おそらくモーダル表示では、Auto Resizing Maskの自動変換が動作する前提となっているのでしょう。

Toolbarなら問題ないですが（さすがにモーダル表示しないでしょう）
統一しておけば迷うこともないので、UIViewControllerを生成した側が外から
`vc.view.translatesAutoresizingMaskIntoConstraints = false`
をしましょう。