JavaScript
iPhone
iOS

WKWebViewで躓いた10つのまとめ

More than 3 years have passed since last update.

WKWebViewについてわかったこと。iOS 8.1.0の時点での情報です。
StackOverflowやDeveloperForumsからの情報と、私がOhajiki Web Browserを開発する過程で得た知識を短めにまとめてみました。
これ以外にもまだまだ細かい部分があるかと思いますが、より良い方法や補足などがありましたらコメント欄で是非とも教えていただければ幸いです。

iOS 9での変更点はこちら: iOS 9 WKWebView 主な変更点をざっくり

tmpフォルダ以外は file:/// を使ってアクセスできない

iOS8.0.2からtmpディレクトリ以下のファイルに fileプロトコルでアクセスすることが可能になりましたが、それ以外のディレクトリからのアクセスは無効となっています。WKWebViewが普及しない一番の要因はこれではないでしょうか。
こちらで試すことが出来ます :link: GitHub shazron / WKWebViewFIleUrlTest

Note: iOS9.0.0(beta)でLibrary/Documents等のフォルダのファイルにアクセス可能になっています。App Bundleは不可。
- (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL NS_AVAILABLE(10_11, 9_0);

Storyboard, Interface Builderで使えない

コード側で初期化・表示しNSLayoutConstraintを設定する必要があります。

target="_blank"のaタグが無反応

そのままではリンクを押しても無反応になってしまいます。
同一のWKWebViewで開くか、新しいWKWebViewを用意する設定をしなければなりません。
:link: WKWebViewでtarget="_blank"なリンクが開かない時の対処法

他アプリへのURLスキームやApp Storeへのリンクは自分で振り分ける必要がある

UIWebViewでは自動でURLスキームやApp Storeのリンクを開いてくれましたが、これもコードを書いて処理する必要があります。
:link: 一例: http://qiita.com/ShingoFukuyama/items/b3a1441025a36ab7659c

JavaScriptの alert, confirm, promptを表示させるためにはWKUIDelegateを使う必要がある

alert, confirm, promptはそれぞれ以下WKUIDelegateのメソッドで処理します。
webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:completionHandler:
webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:completionHandler:
webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:completionHandler:
:link: WKWebViewでJavaScript(Alert,Confirm,Prompt)の処理

Basic, Digestなどの認証の入力画面表示も自分で実装する必要がある

WKNavigationDelegateの以下のメソッドを使います。
webView:didReceiveAuthenticationChallenge:completionHandler:
:link: WKWebViewでBasic認証がかかったページへアクセスする方法 via @qmihara

Cookieを複数のWKWebViewでシェアするにはWKProcessPoolを使う

各WKWebViewの初期化時に共通のWKProcessPoolを指定する必要があります。

例:

self.processPool = [[WKProcessPool alloc] init];

WKWebViewConfiguration *configuration1 = [[WKWebViewConfiguration alloc] init];
configuration1.processPool = self.processPool;
WKWebView *webView1 = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration1];
...
WKWebViewConfiguration *configuration2 = [[WKWebViewConfiguration alloc] init];
configuration2.processPool = self.processPool;
WKWebView *webView2 = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration2];
...

NSCachedURLResponseが使えない

UIWebViewではNSURLCacheとNSCachedURLResponseを使って広告を読み込む前に除外したり、オフラインで読むということが可能でしたがWKWebViewではこの方法は使えません。

Cookie、Cache、Credential、その他Webデータなどを消したい

普通には消せないようです。試行錯誤の結果、以下の方法なら消すことができました。

  1. NSURLCache, NSHTTPCookieを使ってUIWebViewのときと同じようにCookie, Cacheを削除する。もしWKProcessPoolを指定している場合はWKProcessPoolも再度初期化。
  2. Libraryディレクトリ下のCookies, Caches, WebKitサブディレクトリを削除。
  3. すべてのWKWebViewを削除。

リンク長押しで出てくるメニューを無効化できない

CSS: -webkit-touch-callout: none;、またはJavaScript: document.documentElement.style.webkitTouchCallout='none';で無効化できるはずですが、効きません。

Note: iOS8.2から修正されています。

その他

欲しい機能

  • WKWebViewごとのページ履歴の復元: WKBackForwardListがreadonly

参考