LoginSignup
10
10

More than 5 years have passed since last update.

SwiftのWKWebViewでwindow.close()が効かない時がある

Last updated at Posted at 2017-04-27

簡易的なタブブラウザーをSwiftで作っていてjavascriptのwindow.close()が効かない時があり、ハマったので解決法をメモ。

webViewDidCloseが呼ばれない

通常であればWKUIDelegateをデリゲートしていれば、ブラウザが閉じるタイミングでwebViewDidClose()が呼ばれるはずだけど、呼ばれない場合がある。※ブラウザという性質上、web側のjsは弄れず様々な書式で描かれている事が前提。

<a href="javascript:void(0);" onclick="window.close();">閉じる</a>
viewController.swit
func webViewDidClose(_ webView: WKWebView) {
 print("Window close")
}

呼ばれない物の共通点として動的に生成されたコードのイベント処理などがWKUIDelegateで拾えない気がしている。

[解決策] WKScriptMessageHandlerを使う

windowがloadされる前に用意したjsを読み込む

WindowClose.js
 (function () {
  var _close = window.close;
  window.close = function () {
    webkit.messageHandlers.windowClose.postMessage(null);
    _close();
  };
})();
ViewController.swift

//classにWKScriptMessageHandlerを追加

//WKWebViewConfigurationにuserscript追加
let webViewConfiguration = WKWebViewConfiguration()
let userController:WKUserContentController = WKUserContentController()
//messageHandlersの名前を登録
//addScriptMessageHandler() => add()に変わったみたいです。
userController.add(self, name: "windowClose")
//windowがloadされる前にjsを追加
if let path = Bundle.main.path(forResource: "WindowClose", ofType: "js"){
     if let source = try? NSString(contentsOfFile: path, encoding: String.Encoding.utf8.rawValue){
          let userscript = WKUserScript(source: source as String,injectionTime:WKUserScriptInjectionTime.atDocumentEnd,forMainFrameOnly:true)
          userController.addUserScript(userscript)
     }
}

webViewConfiguration.userContentController = userController
let webView = WKWebView(frame: view.bounds, configuration: webViewConfiguration)

//window.closeが呼ばれた場合の処理
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
     if(message.name == "windowClose") {
          print("Window close")
     }
}
ViewController.swift
//window.closeが呼ばれた場合の処理
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
     if(message.name == "windowClose") {
          print("Window close")
     }
}

参考にさせて頂いたページ

Bug 1172928 - Window.close() does not close the tab
https://github.com/mozilla-mobile/firefox-ios/pull/758/files#diff-ae4b3ae1d0a0ca806a652b55ae38509a

[Swift] WKWebView で JavaScript をネイティブ側から実行する
http://qiita.com/takecian/items/9baf7e2bd611aac4791d

swift + javascript 値渡しでWKWebViewはすごかった
http://qiita.com/peta-m175/items/102d6d723fd87e722f83

10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10