見出し画像

iOSアプリで任意のJavaScriptをWebビューに注入しWeb側で実行する方法

chocoZAP iOSアプリ開発を担当している田中です。
アプリ側で固有に保持する値をWebに受け渡す際に、クエリパラメータやCookieを経由するなどいくつかの方法が考えられますが、今回はアプリ側で定義したJavaScript関数をWKWebに注入するという手法を用いたので、その実装方法をご紹介します。


WKUserScriptでスクリプトを定義する

Apple のドキュメントに以下の概要が記されており、まさに今回の要件を満たしてくれそうです。

Create a WKUserScript object when you want to inject custom script code into the pages of your web view.
(筆者訳)カスタムスクリプトをWebビューのページに注入したい場合、WKUserScriptオブジェクトを生成する。

WKUserScript | Apple Developer Documentation

WKUserContentControllerにスクリプトを追加する

ここで生成したスクリプトは、 WKWebConfiguration の持つ userContentController に対して追加することでWeb側から実行できます。

A WKUserContentController object provides a bridge between your app and the JavaScript code running in the web view.
(筆者訳)WKUserContentController オブジェクトは、アプリとWebビュー上で実行するJavaScriptコードとのブリッジを提供する

WKUserContentController | Apple Developer Documentation

追加が可能なタイミングはWKWebConfiguration の初期化時に限らず任意のタイミングで行えます。たとえば WKNavigationDelegate.web(_:didStartProvisionalNavigation:) などでURLの変更を補足して動的に注入することも可能でした。

WKUserScriptは生成時にその注入タイミング injectionTimeをコンテンツのローディング状態に応じて指定することが可能です。Web側でのスクリプト実行タイミングに対して適切な指定をしましょう。

実装例

// ① Web側で実行したい関数を定義する 
let codeText = """ 
function getSomeID() 
{ 
    /* 例:アプリで保持する値をWeb側に連携する */ 
    return "\(someIDValue)" 
} 
""" 
// ② WKWeb にスクリプトを追加する 
let script = WKUserScript(source: codeText, injectionTime: .atDocumentStart, forMainFrameOnly: true) web.configuration.userContentController.addUserScript(script)

Web側では、すでにJavaScriptに注入された関数を呼び出すだけです。

result = getSomeID();
console.log(result);

おわりに

こうしたWebからアプリ側の処理を呼び出す機会は、個人的にあまり多くなく知見が乏しかったため、勉強になりました。

[参照]
WKUserScript | Apple Developer Documentation
WKUserContentController | Apple Developer Documentation
WKUserScriptInjectionTime | Apple Developer Documentation



いいなと思ったら応援しよう!