代码之家  ›  专栏  ›  技术社区  ›  Aaron Brager

如何使用ios wkwebview注入javascript回调以检测onclick事件?

  •  12
  • Aaron Brager  · 技术社区  · 6 年前

    我用的是 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 实施

    当我单击WebView中的任何按钮时,在我的 WKNavigationDelegate :

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

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

    什么是最简单的方法来检测何时点击这个按钮?

    我想在用户单击时响应 提交 忽略其他按键。

    我看到了一些关于栈溢出的其他方法 WKUserContentController 但它们似乎要求网站调用以下内容:

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

    我无法控制此网站,因此无法将此行添加到其源代码中,而且我不知道如何使用 WKWebVIEW .

    3 回复  |  直到 6 年前
        1
  •  2
  •   Kousic    6 年前

    用户脚本是在文档加载开始或文档加载完成后注入到网页中的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>) 方法。 这里,__name_157;是要回发的消息的名称。JS可以将任何JS对象作为消息体发回,JS对象将自动映射到相应的Swift本机对象。 下面的JS代码片段在ID为__ClickMeButton_157;的按钮上发生按钮单击事件时回发消息。

    varbutton = 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")
    
        2
  •  2
  •   Constantino Tsarouhas    6 年前

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

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

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

        3
  •  2
  •   Bharata colxi    6 年前

    您可以使用 evaluateJavaScript() 函数到 WKWebView . 你可以捕获所有 onclick 具有以下JS代码的事件,仅检测单击 submit 按钮。所有原始事件处理程序也将运行-别担心!

    document.addEventListener("click", function(e)
    {
        e = e || window.event;
        //if(e.target.value == 'Submit') //you can identify this button like this, but better like:
        if(e.target.getAttribute('onclick') == 'javascript:GotoURL(3)')
        //if this site has more elements with onclick="javascript:GotoURL(3)"
        //if(e.target.value == 'Submit' && e.target.getAttribute('onclick') == 'javascript:GotoURL(3)')
        {
            console.log(e.target.value);
            //if you need then you can call the following line on this place too:
            //window.webkit.messageHandlers.log.postMessage("submit");
        }
    });
    
    //DO NOT add the next line in your code! It is only for my demo - buttons need this in my demo for execution
    function GotoURL(site){}//DO NOT add this line! It is only for my demo!
    <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)">