SwiftでWKWebViewとKey-Value Observingを使ってWebページの読込み状況を取得する

More than 3 years have passed since last update.

iOS8から、WKWebViewというWebKitをベースとしたWebビューを使うことができるようになりました。ここではSwiftでWKWebViewと新たに増えた監視可能(KVO compliant)なプロパティを使ってみます。


WKWebViewの用意

WKWebViewは現時点ではコードを使って実装します。UIWebViewとは異なりXcodeのInterface Builderから配置することは今の所できません。

var webView:WKWebView?

override func loadView() {
self.webView = WKWebView()
self.view = self.webView!
}

override func viewDidLoad() {
super.viewDidLoad()

let requestURL = NSURL(string: "http://www.apple.com")
let req = NSURLRequest(URL: requestURL!)
self.webView!.loadRequest(req)
}


Webページの読込み状況を取得

WKWebKitではUIWebViewでは未提供のプロパティが新たに追加されましたが、その一つとしてWebページの読込み状況を表すestimatedProgressがあります。

更にestimatedProgressはKey Value Observing(KVO)に対応しています。予めこうしたプロパティを監視しておくことで値が変化した時に自動的に処理を実行することができます。

ここではWebページの読込み状況を監視して、自動的にコンソールに出力してみます。



  1. 監視対象の登録

    override func viewDidLoad() {
    
    // 省略
    self.webView?.addObserver(self, forKeyPath:"estimatedProgress", options:.New, context:nil)
    }



  2. 監視解除

    SwiftではKVOの監視解除をdeinitの中で記述します。

    deinit {
    
    self.webView?.removeObserver(self, forKeyPath: "estimatedProgress")
    }



  3. 値が変化した時の処理

    override func observeValueForKeyPath(keyPath:String, ofObject object:AnyObject, change:[NSObject:AnyObject], context:UnsafeMutablePointer<Void>) {
    
    switch keyPath {
    case "estimatedProgress":
    if let progress = change[NSKeyValueChangeNewKey] as? Float {
    println("Progress:\(progress)")
    }
    default:
    break
    }
    }


Web viewを開くとページの読み込み状況に応じて、コンソールに自動的に進捗状況が出力されます。


監視可能(KVO Compliant)なプロパティ一覧

WkWebViewのクラスリファレンスによると、以下のようなプロパティがKVO Compliantとのことです。


  • title

  • URL

  • estimatedProgress

  • loading

これによりWebサイトloadingのインジケーター(networkActivityIndicatorVisible)を以前と異なる方法で実装できるようになるなど、WebView関連の処理が楽になりました。

以下では例としてtitleの監視を行います。


Webサイトのタイトルをページ遷移するたびにナビゲーションバーに自動的に表示させる

表示しているWebサイトのタイトルを検知してナビゲーションバーに表示させる例です。記述場所はそれぞれ上と同じです。

監視

self.webView?.addObserver(self, forKeyPath:"title", options:.New, context:nil)

監視解除

self.webView?.removeObserver(self, forKeyPath: "title")

値変化時の処理

case "title":

if let title = change[NSKeyValueChangeNewKey] as? NSString {
self.navigationItem.title = title
}


参考