WKWebViewでnetworkActivityIndicatorVisibleを表示

(追記) iOS10 になって色々変わっていたので、書き直した。

networkActivityIndicatorVisible (iPhoneの上部のステータスバーで読込中にぐるぐるさせるやつ) を表示する方法。UIWebView は、html,js,css,画像などの区別がつかなくて結構たいへんだったけど、そういうの気にせずだいぶ楽に実装できる。

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 func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
    if keyPath == "loading" {
        UIApplication.sharedApplication().networkActivityIndicatorVisible = webView.loading
    }
}

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

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

WKWebView を使って、特に何もせず networkActivityIndicatorVisible だけを変えたい場合は、下記のようなサブクラスを作って WKWebView を呼んでるところに置き換えれば良い。

import UIKit
import WebKit

class CustomWebView: WKWebView {
    init() {
        super.init(frame: CGRectZero, configuration: WKWebViewConfiguration())
        self.translatesAutoresizingMaskIntoConstraints = false

        addObserver(self, forKeyPath: "loading", options: NSKeyValueObservingOptions.New, context: nil)
    }
    
    deinit {
        removeObserver(self, forKeyPath: "loading")
    }
    
    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
        if keyPath == "loading" {
            UIApplication.sharedApplication().networkActivityIndicatorVisible = loading
        }
    }
}

使い方

全画面表示で、特定のURLを読み込むというもの。

let webView = CustomWebView()

view.addSubview(webView)
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[webView]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["webView": webView]))
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[webView]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["webView": webView]))

webView.loadRequest(NSURL(string : "https://memo.ecp.plus/"))

Contents