如何使用 iOS WKWebView 注入 JavaScript 回调来检测 onclick 事件?

新手上路,请多包涵

我正在使用 WKWebView 来显示一个包含三个按钮的 HTML 的网站。单击特定按钮时,我想在本机应用程序中运行一些 Swift 代码。

关于 HTML

三个按钮如下所示:

 <input type="button" value="Edit Info" class="button" onclick="javascript:GotoURL(1)">
<input type="button" value="Start Over" class="button" onclick="javascript:GotoURL(2)">
<input type="button" value="Submit" class="button" onclick="javascript:GotoURL(3)">

他们调用的 GotoURL 函数如下所示:

 function GotoURL(site)
{
    if (site == '1')
        document.myWebForm.action = 'Controller?op=editinfo';
    if (site == '2')
        document.myWebForm.action = 'Controller?op=reset';
    if (site == '3')
        document.myWebForm.action = 'Controller?op=csrupdate';
    document.myWebForm.submit();
}

当前 WKWebView 实施

当我单击 web 视图中的任何按钮时,将在我的 WKNavigationDelegate 上调用此函数:

 func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
    // ...?
}

但当然, navigation 是不透明的,因此不包含有关用户单击了三个按钮中的哪一个的信息。

检测何时单击此按钮的最简单方法是什么?

我想在用户单击 提交 并忽略其他按钮按下时做出响应。

我在 Stack Overflow 上看到了其他一些使用 WKUserContentController 的方法,但它们似乎要求网站调用如下内容:

 window.webkit.messageHandlers.log.postMessage("submit");

我不控制这个网站,所以我不能在它的源代码中添加这一行,而且我不知道使用 WKWebView 将它注入正确位置的最佳方法。

原文由 Aaron Brager 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

用户脚本是在文档加载开始或文档加载完成后注入网页的 JS。用户脚本非常强大,因为它们允许对网页进行客户端自定义,允许注入事件侦听器,甚至可以用于注入脚本,这些脚本可以反过来回调到本机应用程序。以下代码片段创建了一个在文档加载结束时注入的用户脚本。用户脚本被添加到 WKUserContentController 实例,该实例是 WKWebViewConfiguration 对象的一个属性。

 // Create WKWebViewConfiguration instance
  var webCfg:WKWebViewConfiguration = WKWebViewConfiguration()

  // Setup WKUserContentController instance for injecting user script
  var userController:WKUserContentController = WKUserContentController()

  // Get script that's to be injected into the document
  let js:String = buttonClickEventTriggeredScriptToAddToDocument()

  // Specify when and where and what user script needs to be injected into the web document
  var userScript:WKUserScript =  WKUserScript(source: js,
                                         injectionTime: WKUserScriptInjectionTime.atDocumentEnd,
                                         forMainFrameOnly: false)

  // Add the user script to the WKUserContentController instance
  userController.addUserScript(userScript)

  // Configure the WKWebViewConfiguration instance with the WKUserContentController
  webCfg.userContentController = userController;

您的网页可以通过 window.webkit.messageHandlers.<name>.postMessage (<message body>) 方法将消息发布到您的本机应用程序。此处,“名称”是回发消息的名称。 JS 可以回发任何 JS 对象作为消息体,JS 对象会自动映射到相应的 Swift 原生对象。以下 JS 代码片段在 ID 为“ClickMeButton”的按钮上发生按钮单击事件时回发一条消息。

 var button = document.getElementById("clickMeButton");
button.addEventListener("click", function() {
            varmessageToPost = {'ButtonId':'clickMeButton'};
            window.webkit.messageHandlers.buttonClicked.postMessage(messageToPost);
        },false);

为了接收您的网页发布的消息,您的本机应用程序需要实现 WKScriptMessageHandler 协议。该协议定义了一个必需的方法。可以查询回调中返回的 WKScriptMessage 实例以获取有关正在回发的消息的详细信息。

 func userContentController(userContentController: WKUserContentController,
                           didReceiveScriptMessage message: WKScriptMessage) {

        if let messageBody:NSDictionary= message.body as? NSDictionary{
            // Do stuff with messageBody
        }

    }

最后,实现 WKScriptMessageHandler 协议的本地类需要将自己注册为 WKWebView 的消息处理程序,如下所示:

 // Add a script message handler for receiving  "buttonClicked" event notifications posted
// from the JS document
userController.addScriptMessageHandler(self, name: "buttonClicked")

原文由 Kousic 发布,翻译遵循 CC BY-SA 4.0 许可协议

您始终可以在 Web 视图上使用 evaluateJavaScript(_:) 注入源代码。从那里,替换按钮上的事件处理程序(发布消息然后调用新处理程序中的原始函数)或在按钮上添加事件处理程序或捕获点击事件并发布消息的祖先元素。 (原始事件处理程序也将运行。)

 document.getElementById("submit-button").addEventListener("click", function () {
   window.webkit.messageHandlers.log.postMessage("submit");
});

如果按钮没有 ID,您可以在文档上添加一个处理程序来捕获所有(冒泡的)点击事件,然后根据事件目标(使用按钮的文本或位置作为决定因素)发布消息。

原文由 Constantino Tsarouhas 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题