WKWebViewとJavaScriptの連携

WKWebViewとJavaScriptを連携すると、いろいろな処理が実現できます。

アプリはSwiftとSwiftUI、サーバはHTMLとCSS(JavaScript)でコードを書いてみました。

サンプルサイト

適当な文字列を入力するとXcodeのログに出力されます。

Xcodeの出力。1文字ごとに出力される。

今回は以下の手順でテキストボックスの入力情報を取得します。

  • WebViewでJavaScriptを挿入
  • ユーザがWebページのテキストボックスに入力
  • 入力と同時にJSからアプリへ入力値を送信する

WebViewとJSのコードをそれぞれ解説していきます。

Webページ

テキストボックスを2つ設置したシンプルなWebサイトを作ります。

    <form action="" method="get">
      <div>
        <label for="email">Enter your email: </label>
        <input type="email" name="email" id="email" required />
      </div>
      <div>
        <label for="pass">Enter your password: </label>
        <input type="password" name="password" id="pass" required />
      </div>
      <div>
        <input type="submit" value="Sign in" />
      </div>
    </form>
    <p class="log"></p>
    <p class="log2"></p>
    <p class="log3">This is Sample.</p>

アプリ(WKWebView)

SwiftUIでWKWebViewを使えるようにします。

struct WebViewContainer: UIViewRepresentable { ... }

Coordinatorで各種Delegateを使えるようにします。

class Coordinator: NSObject, WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler { ... }

以下の関数はページの読み込みが終わったタイミングで呼ばれます。

        // JSを実行する
     func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            webView.evaluateJavaScript("ここに実行するJSを記載します。")
            webView.configuration.userContentController.add(self, name: "changeTextbox")
        }
        // JSからのデータを受け取る
        func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
            if(message.name == "changeTextbox"){
                let param = message.body as! String
                print(param)
            }
        }

evaluateJavaScriptで、JSを実行することができます。

実行するJSは文字列で指定します。(文字列で記載すると見づらいので別途JSとして記載)

ちなみに、evaluateJavaScriptはcompletionHandlerを使って実行結果を受け取ることもできます。

changeTextboxという名前の関数を登録しておき、データをuserContentContollerのdidReceiveで受け取ります。

evaluateJavaScriptで実行するJSは以下の通り。

// input要素のidを指定する
const email = document.querySelector('#email');
// 出力用のp要素のclass名と関数名をオブジェクトにして渡す。
email.addEventListener('input', {outputname: '.log',handleEvent:handleChange});

const pass = document.querySelector('#pass');
pass.addEventListener('input', {outputname: '.log2',handleEvent:handleChange});

// inputの値が変わるたびに呼ばれる。
function handleChange(event){
    const value = event.target.value;
    document.querySelector(this.outputname).innerHTML = value;
    webkit.messageHandlers.changeTextbox.postMessage(value)
}

changeTextbox.postMessageで入力データをアプリ側に送信します。

まとめ

シンプルなコードでWebViewでJSを実行してユーザのデータを取得することができました。

便利な反面、悪用されると怖いのでJSやWebViewの取り扱いには注意が必要です。

ABOUTこの記事をかいた人

個人アプリ開発者。Python、Swift、Unityのことを発信します。月間2.5万PVブログ運営。 Twitter:@yamagablog