How to inject JavaScript callback to detect onclick event, using iOS WKWebView?

前端 未结 4 1554
灰色年华
灰色年华 2021-02-01 06:14

I\'m using a WKWebView to show a website which has some HTML that includes three buttons. I want to run some Swift code in the native app when a specific button is

相关标签:
4条回答
  • 2021-02-01 06:23

    You can always inject source code using evaluateJavaScript(_:) on the web view. From there, either replace the event handler on the buttons (posting a message and then invoking the original function in the new handler) or add an event handler on the buttons or an ancestor element that captures click events and posts a message. (The original event handler will also run.)

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

    If the buttons don’t have an ID, you can add a handler on the document that captures all (bubbling) click events and then posts a message based on the event target (using the button’s text or location as a determinant).

    0 讨论(0)
  • 2021-02-01 06:31

    Here goes the implementation in detail:

     var webView: WKWebView?
     var webConfig:WKWebViewConfiguration {
     get {
    
        let webCfg:WKWebViewConfiguration = WKWebViewConfiguration()
        let userController:WKUserContentController = WKUserContentController()
        userController.add(self, name: "submit")
        let js:String = buttonClickEventTriggered()
        let userScript:WKUserScript =  WKUserScript(source: js, injectionTime:WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: false)
        userController.addUserScript(userScript)
        webCfg.userContentController = userController;
        return webCfg;
    }
    }
    override func viewDidLoad() {
    super.viewDidLoad()
    self.webView = WKWebView(frame: self.view.frame, configuration: webConfig)
    self.webView!.navigationDelegate = self
    self.view = webView!
    let url = URL(string:"your URL here")
    let req = NSURLRequest(url:url! as URL)
    self.webView!.load(req as URLRequest)
    }
    
     func buttonClickEventTriggered() ->String{
    
    let script:String = "document.getElementById('your button id here').addEventListener('click', function () {window.webkit.messageHandlers.submit.postMessage('submited');});"//Make sure you have mapped the name correctly under userController.add
    return script;
    }
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    print("Sucessss")
    if(message.name == "submit") {
        print("It does ! \(message.body)")
        // Your code goes here
    }
    }
    
    0 讨论(0)
  • 2021-02-01 06:38

    You can inject JS code using evaluateJavaScript() function to the WKWebView. You can capture all onclick events with following JS code, which detect only the click on submit button. All original event handlers will also run - don't worry!

    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)">

    0 讨论(0)
  • 2021-02-01 06:39

    User Scripts are JS that you inject into your web page at either the start of the document load or after the document is done loading. User scripts are extremely powerful because they allow client-side customization of web page, allow injection of event listeners and can even be used to inject scripts that can in turn call back into the Native app. The following code snippet creates a user script that is injected at end of document load. The user script is added to the WKUserContentController instance that is a property on the WKWebViewConfiguration object.

    // 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;
    

    Your web page can post messages to your native app via the window.webkit.messageHandlers.<name>.postMessage (<message body>) method. Here, “name” is the name of the message being posted back. The JS can post back any JS object as message body and the JS object would be automatically mapped to corresponding Swift native object. The following JS code snippet posts back a message when a button click event occurs on a button with Id “ClickMeButton”.

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

    In order to receive messages posted by your web page, your native app needs to implement the WKScriptMessageHandler protocol. The protocol defines a single required method. The WKScriptMessage instance returned in the callback can be queried for details on the message being posted back.

    func userContentController(userContentController: WKUserContentController,
                               didReceiveScriptMessage message: WKScriptMessage) {
    
            if let messageBody:NSDictionary= message.body as? NSDictionary{
                // Do stuff with messageBody
            }
    
        }
    

    Finally, the native class that implements WKScriptMessageHandler protocol needs to register itself as a message handler with the WKWebView as follows:

    // Add a script message handler for receiving  "buttonClicked" event notifications posted 
    // from the JS document
    userController.addScriptMessageHandler(self, name: "buttonClicked")
    
    0 讨论(0)
提交回复
热议问题