UITabbarControllerのWebViewを先読み（プリロード）して、表示速度を高速化する。

UITabbarControllerにWKWebViewを配置した場合、タブが切り替わってからロードが走りWebViewが表示されるのでロード待ちの時間が発生し、ページが表示されるまにで時間がかかってしまう。

これを改善するために裏側でロードを走らせてロード待ちの時間を短縮し、ページの表示速度を上げることが出来ましたのでご紹介します。

# ■ポイント
1. initでwebViewを読み込んでおく。
   XibでViewを用意しておく。（あとでwebviewを追加する用） 
2. initの段階ではWebviewの制約は仮で設定しておく。
3. viewDidLoadで用意していたXibのViewにWebViewを追加して、正しい制約をかける。

## 1. initでWebViewを読み込んでおく。
viewDidLoadでページをロードをしているからロード時間が発生していた。
└　initの段階でページのロードを走らせたい。


+ initでwebViewを使いたいのでwebViewだけはXibで作らない。
（理由：Xibで作ったViewは、viewDidLoadから使えるようになるのでinitでは使えない為）
+ あとでwebViewをaddSubViewする為の箱を用意する。(webViewContainer)
```swift
    // webView入れる用の箱を用意する。
    @IBOutlet weak var webViewContainer: UIView!
    @IBOutlet weak var loadingView: UIActivityIndicatorView!
    @IBOutlet weak var errorView: UIView!
    // initでwebViewを使いたいのでXibで作らない。
    private var webView: WKWebView?

    init() {
        super.init(nibName: nil, bundle: nil)
        // イニシャライザでローディングする。
        preloadWebView()
    }
```

## 2. initの段階ではWebViewの制約は仮で設定しておく。（viewDidLoadで正しい制約をつける）

```swift
    private func preloadWebView() {
        let config = WKWebViewConfiguration()
        config.allowsInlineMediaPlayback = true
        config.mediaTypesRequiringUserActionForPlayback = []
        
        // 仮の制約をかける
        let width = UIScreen.main.bounds.size.width
        let height = UIScreen.main.bounds.size.height
        webView = WKWebView(frame: CGRect(x: 0, y: 0, width: width, height: height), configuration: config)

        loadWebView()
    }

    private func loadWebView() {
        guard let webView = webView else {
            return
        }
        guard let url = URL(string: "https://www.google.com") else {
            return
        }

        let request = URLRequest(
            url: url,
            cachePolicy: .reloadIgnoringLocalAndRemoteCacheData,
            timeoutInterval: 10
        )

        webView.navigationDelegate = self
        webView.load(request)
    }
```

## 3. viewDidLoadで用意していたXibのViewにWebViewを追加して、正しい制約をかける。

```swift
    override func viewDidLoad() {
        super.viewDidLoad()
        createWebView()
    }

    private func createWebView() {
        guard let webView = webView else {
            return
        }
        if !webView.isDescendant(of: webViewContainer) {
            // 用意していたview(webViewContainer）にWebViewをaddSubViewする。
            self.webViewContainer.addSubview(webView)
            webView.translatesAutoresizingMaskIntoConstraints = false

            // 正しい制約をかける。
            let constraints = [
                webView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
                webView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor),
                webView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor),
                webView.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor)
            ]
            NSLayoutConstraint.activate(constraints)
        }
    }
```


# ■全体のコード
```swift:WebViewController.swift
    @IBOutlet weak var webViewContainer: UIView!
    @IBOutlet weak var loadingView: UIActivityIndicatorView!
    @IBOutlet weak var errorView: UIView!
    private var webView: WKWebView?
    
    init(webViewConfig: WebViewConfig) {
        super.init(nibName: nil, bundle: nil)
        preloadWebView()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        createWebView()
    }

    private func preloadWebView() {
        let config = WKWebViewConfiguration()
        config.allowsInlineMediaPlayback = true
        config.mediaTypesRequiringUserActionForPlayback = []

        let width = UIScreen.main.bounds.size.width
        let height = UIScreen.main.bounds.size.height
        webView = WKWebView(frame: CGRect(x: 0, y: 0, width: width, height: height), configuration: config)

        loadWebView()
    }

    private func createWebView() {
        guard let webView = webView else {
            return
        }
        if !webView.isDescendant(of: webViewContainer) {
            self.webViewContainer.addSubview(webView)
            webView.translatesAutoresizingMaskIntoConstraints = false

            let constraints = [
                webView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor),
                webView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor),
                webView.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor),
                webView.leadingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.leadingAnchor)
            ]
            NSLayoutConstraint.activate(constraints)
        }
    }

    private func loadWebView() {
        guard let webView = webView else {
            return
        }
        guard let url = URL(string: "https://www.google.com") else {
            return
        }

        let request = URLRequest(
            url: url,
            cachePolicy: .reloadIgnoringLocalAndRemoteCacheData,
            timeoutInterval: 10
        )

        webView.navigationDelegate = self
        webView.load(request)
    }
```