iOS 8から追加されたWebKit Frameworkを使ってみる

※本記事は、[一般に公開されている情報](https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/WebKit/ObjC_classic/index.html)を元に作成しています。

iOS 8から新たに __WebKit Framework__ が追加されました。

これにより、ようやくWebページのロードプログレスが取得できるようになったり、JavaScriptエラーを受け取れるようになりました。

クラスリファレンス等はすでに一般にも公開されており、開発者以外も読むことができます。

https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/WebKit/ObjC_classic/index.html

以下、私が気になった項目をまとめていきたいと思います。

## UIWebViewとの関係

従来の UIWebView と WebKit Framework は別物のようです。（勝手にUIWebViewの機能強化版だと思い込んでいた）

新たに `WKWebView` というクラスが用意されていました。

- [WKWebView Class Reference](https://developer.apple.com/library/prerelease/ios/documentation/WebKit/Reference/WKWebView_Ref/index.html)

## 初期化

WebKit Framework をインポート。

```objc
@import WebKit;
```

`WKWebView` インスタンスの生成。`configuration` については後述。

```objc
self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds
                                  configuration:configuration];
```

## プロパティ

### configuration

WebViewの設定。`WKWebViewConfiguration` を指定できます。

`WKWebViewConfiguration` クラスには `preference` というプロパティがあり、

- WebViewの最小フォントサイズ
- データの取得が完了するまで描画を行わない
- JavaScriptが新ウィンドウを自動的に開くのを許可するか
- JavaScriptの実行を許可するか

などを設定できるようです。詳しくは次のクラスリファレンスを参照してください。

- [WKPreferences](https://developer.apple.com/library/prerelease/ios/documentation/WebKit/Reference/WKPreferences_Ref/index.html)

### navigationDelegate

WebViewのナビゲーションに関するデリゲートです。詳しくは後述します。

### title

現在表示しているページのタイトルが `NSString` で取得できるようになりました。今後は

```objc
NSString* title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
```

のような処理を書かなくても良いわけですな！

ちなみに、`URL` プロパティで表示中の url も取得できます。

### estimatedProgress

ついにページのロードプログレスがiOS標準で取得できるようになりました！このプロパティは `double` 型で、0.0 から 1.0 の値が入ります。ページの読み込みが完了すると 1.0 になり、新たなページの読み込みが始まると再び 0.0 にリセットされるようです。

### allowsBackForwardNavigationGestures

iOS 7 から Safari に追加された「フリックで前ページに戻る・進む」がついに WebView でも使えるようになりました！このプロパティを `YES` にすることで機能が有効になります。デフォルトは `NO` のようです。

### backForwardList

Webページの閲覧履歴が WebView でも扱えるようになりました。今までに閲覧してきたページのリストが `WKBackForwardList` クラスで取得できます。

このクラスは次のプロパティから構成されます。（例：A -> B -> C の3つのページを閲覧したあと、「戻る」で B のページに戻った場合）

- currentItem - 現在表示しているページ（B）
- backItem - 「戻る」で表示されるページ（A）
- forwardItem - 「進む」で表示されるページ（C）
- backList - 「戻る」で表示できるページのリスト（`NSArray`）
- forwardList - 「進む」で表示できるページのリスト（`NSArray`）

各ページの情報は `WKBackForwardListItem` クラスで管理されており、タイトルとURLが取得できます。

## メソッド

### - reloadFromOrigin

通常の `reload` メソッドとは別にこのメソッドが用意されていました。ドキュメントには

>Reloads the current page, performing end-to-end revalidation using cache-validating conditionals if possible.

のように書かれていました。（キャッシュを使わないリロードのこと？）

## デリゲート

UIWebView と同じように、様々なデリゲートが用意されています。

例えば、あるWebページを表示しようとすると、次の順番でデリゲートが呼ばれます。

```objc
- (void)webView:(WKWebView *)webView
 didStartProvisionalNavigation:(WKNavigation *)navigation
```

ページの読み込み準備開始。この時点での `estimatedProgress` は `0.1` でした。

```objc
- (void)webView:(WKWebView *)webView
 didCommitNavigation:(WKNavigation *)navigation
```

ページが見つかり、読み込み開始。この時点での `estimatedProgress` は `0.3` 以上の値が入っていました。（ちなみにページが見つからない場合、このデリゲートは呼ばれませんでした）

```objc
- (void)webView:(WKWebView *)webView
didFinishNavigation:(WKNavigation *)navigation
```

ページの読み込み完了。この時点での `estimatedProgress` は `1.0` でした。

ここまでがひとつのページをリクエストした時の動きです。

----

その他のデリゲートは以下のとおり。

```objc
- (void)webView:(WKWebView *)webView
 didFailProvisionalNavigation:(WKNavigation *)navigation
      withError:(NSError *)error
```

ページの読み込み失敗。この時点での `estimatedProgress` は `0.1` だったり `1.0` だったり色々。 

```objc
- (void)webView:(WKWebView *)webView
didFailNavigation:(WKNavigation *)navigation
      withError:(NSError *)error
```

調査中。ページは見つかったけど表示できない場合？

```objc
- (void)webView:(WKWebView *)webView
didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation
```

表示中にリダイレクトが入ると呼ばれるようです。

## パフォーマンスとか

[9to5mac](http://9to5mac.com/) の情報によると、これまで Safari だけが使うことができた高速な JavaScript エンジン（Nitro）を、iOS 8 から追加された WebKit Framework でついに使えるようになる！とのことです。

- [iOS 8 WebKit changes finally allow all apps to have the same performance as Safari](http://9to5mac.com/2014/06/03/ios-8-webkit-changes-finally-allow-all-apps-to-have-the-same-performance-as-safari/)

今後は、サードパーティ製ブラウザや、アプリ内ブラウザの速度向上が期待できそうですね！