WKWebView で NetworkActivityIndicator を良い感じに表示(Swift3)

以前 iOS9 が出たときに書いたものが古くて使えなくなってたので、書き直した。

iOS9とSwift2の頃のやり方

iOS9 から追加された WKWebView で、networkActivityIndicator (iPhoneの上部のステータスバーで読込中にぐるぐるさせるやつ) を表示する方法。 UIWebView と WebView はもう使うなって API Reference に書いてある。

Swift3 になって書き方も変わっているのと、iOS9 から constrains の設定もしやすくなった。WebView の一種でコンテンツを読み込むとき、isNetworkActivityIndicatorVisible を処理しないことが無かったので、 pod でインストール出来るようにした。

EcpWebView (on GitHub)

Controller に直接書くパターン

KVOを監視する

Controller に直接書く場合は、viewDidLoad とかで、addObserver する。

var webView : WKWebView!

的なプロパティが設定してあるという前提で

webView.addObserver(self, forKeyPath: "loading", options: NSKeyValueObservingOptions.New, context: nil)

とする。

controller がなくなるタイミングで

webView.removeObserver(self, forKeyPath: "loading")

を呼ぶのを忘れずに。

KVOの変化にフックさせる

override public func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == "loading" {
        UIApplication.shared.isNetworkActivityIndicatorVisible = isLoading
    }
}

loading状態が変わると、このメソッドが呼ばれるので、そのタイミングで webView.loading (BOOL) がどうなっているのかを見るだけで良い。

WKWebView のサブクラスを作るパターン

EcpWebView (on GitHub) にあげてあります。

コード的には、 EcpWebView.swift (on GitHub) です。

Installation

# required Swift 3.0
pod 'EcpWebView'

として、 import EcpWebView とすれば、WKWebView で書いていたところを置き換えるだけで使えるはずです。

Usage

WKWebView は StoryBoard から使えないので、コードで追加するしかない(多分)。全画面表示で、特定のURLを読み込むという場合の例。iOS9 から constraint が書きやすくなったのと、Swift3 から NSURLRequest -> URLRequest, NSURL -> URL となって、 WKWebView も、 loadRequest -> load となった。 UIApplication も sharedApplication() -> application となってた。Xcode が全部教えてくれるので楽だ。

let webView = EcpWebView()
view.addSubview(webView)

webView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
webView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
webView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
webView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true

let req = URLRequest(url: URL(string: "https://memo.ecp.plus/")!)
webView.load(req)
WKWebView で NetworkActivityIndicator を良い感じに表示(Swift3)