WKWebViewのローディング表示まとめ【Swift】


WKWebViewのLoading表示
どの手段が適切かな🤔
と気になったのでまとめてみました



## 1. StatusBarに表示

                
 　　　　　　 👇
![statusbar.gif](https://qiita-image-store.s3.amazonaws.com/0/119392/6a1d1a4b-41d7-609d-1b3f-b4f08e3f3ed8.gif)

[networkactivityindicatorvisible](https://developer.apple.com/documentation/uikit/uiapplication/1623102-networkactivityindicatorvisible)を活用

```swift:ViewController.swift

@IBOutlet weak var webView: WKWebView!

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

private func startIndicator() {
    UIApplication.shared.isNetworkActivityIndicatorVisible = true
}

private func stopIndicator() {
    UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
```

WKNavigationDelegateを実装

```swift:ViewController.swift
extension StatusBarLoadingViewController: WKNavigationDelegate {
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        startIndicator()
    }

    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        stopIndicator()
    }

    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        stopIndicator()
    }

    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
        stopIndicator()
    }
}
```

ただし、ノッジのあるiPhoneXシリーズだとくるくるが表示されないためイマイチ😢

## 2. UIActivityIndicatorViewで表示
![activity.gif](https://qiita-image-store.s3.amazonaws.com/0/119392/6b0802bb-366f-fd38-3460-83bcab00a3a8.gif)


```swift:ViewController.swift
@IBOutlet weak var webView: WKWebView!
@IBOutlet weak var activityIndicatorView: UIActivityIndicatorView!

override func viewDidLoad() {
    super.viewDidLoad()
    let request = URLRequest(url: URL(string: "https://koooootake.com/")!)
    webView.load(request)
    webView.navigationDelegate = self
    activityIndicatorView.hidesWhenStopped = true
}

private func startIndicator() {
    activityIndicatorView.startAnimating()
}

private func stopIndicator() {
    activityIndicatorView.stopAnimating()
}
```
と1. と同じくWKNavigationDelegateを実装

シンプルに読み込み中であることが伝わる😀

## 3. UIProgressViewで受信状況を表示
![progress.gif](https://qiita-image-store.s3.amazonaws.com/0/119392/5b5b7500-c3a8-d753-bff6-2a92897f3359.gif)

[estimatedProgress](https://developer.apple.com/documentation/webkit/wkwebview/1415007-estimatedprogress)を活用

```swift:ViewController.swift
@IBOutlet weak var webView: WKWebView!
private var progressView = UIProgressView(progressViewStyle: .bar)

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

private func setupProgressView() {
    guard let navigationBarH = self.navigationController?.navigationBar.frame.size.height else {
        assertionFailure()
        return
    }
    progressView = UIProgressView(frame: CGRect(x: 0.0, y: navigationBarH, width: self.view.frame.size.width, height: 0.0))
    navigationController?.navigationBar.addSubview(progressView)
    //変更を検知
    webView.addObserver(self, forKeyPath: #keyPath(WKWebView.isLoading), options: .new, context: nil)
    webView.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: .new, context: nil)
}
```

検知した変更をUIに反映

```swift:ViewController.swift
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
    guard let keyPath = keyPath else {
        assertionFailure()
        return
    }

    switch keyPath {
    case #keyPath(WKWebView.isLoading):
        if webView.isLoading {
            progressView.alpha = 1.0
            progressView.setProgress(0.1, animated: true)
        } else {
            UIView.animate(withDuration: 0.3, animations: {
                self.progressView.alpha = 0.0
            }, completion: { _ in
                self.progressView.setProgress(0.0, animated: false)
            })
        }
    case #keyPath(WKWebView.estimatedProgress):
        self.progressView.setProgress(Float(webView.estimatedProgress), animated: true)
    default:
        //do nothing
        break
    }
}
```
あとどれくらいで終わるか伝わるので、待機ストレスがなくなる予感ですねねね🤩

## おわりに
引っ張ってリロードとの表示のバッティングに注意！

オシャレなアニメーションライブラリと組み合わせてもなおよし
適切なローディング表示を選択しよう🙋‍♂️

> Swift4