3

I am trying to call native function in swift from wkwebview. This is what I have done so far:

Swift Part

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    contentController.add(self, name: "backHomePage")

    config.userContentController = contentController
    self.webView = WKWebView(frame: self.containerView.bounds, configuration: config)

    webView.navigationDelegate = self

    self.containerView.addSubview(self.webView)
    if let url = URL(string: assessmentLink) {
        webView.load(URLRequest(url: url))
    }
}

And

extension WebFormVC: WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        print("javascript sending \(message.name), body: \(message.body)")
    }
}

Javascript

function backHomePage(message) {
    window.webkit.messageHandlers.backHomePage.postMessage(message);
}

where message can be any string for example: "success"

I am not currently receiving call back in userContentController didReceive method

UPDATE

I also tried sending data as key value for example window.webkit.messageHandlers.backHomePage.postMessage({"message" :"Javascript to swift!"}); , and it still didn't work.

2 Answers 2

3

I've tried to reproduce your case and everything seems to work as expected

import UIKit
import WebKit

class ViewController: UIViewController, WKScriptMessageHandler {
  let content = """
  <!DOCTYPE html><html><body>
  <button onclick="onClick()">Click me</button>
  <script>
  function onClick() {
    window.webkit.messageHandlers.backHomePage.postMessage("success");
  }
  </script>
  </body></html>
  """

  override func viewDidLoad() {
    super.viewDidLoad()

    let config = WKWebViewConfiguration()
    config.userContentController = WKUserContentController()
    config.userContentController.add(self, name: "backHomePage")

    let webView = WKWebView(frame: CGRect(x: 0, y: 0, width: 200, height: 200), configuration: config)

    view.addSubview(webView)

    webView.loadHTMLString(content, baseURL: nil)
  }

  func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    print(message.body)
  }
}
Sign up to request clarification or add additional context in comments.

6 Comments

The script shown in question is already present in webpage that is being accessed through wkwebview and is being called at appropriate button click in the webpage. Do I still need to add script to userContentController?
I haven’t tried to do this without adding script to controller.
The javascript function is on the webpage and is called when user taps submit button of the form in that page. The message parameter will be string as result of action such as "success" or "failure"
ok @Andy so taking a simple webpage as string and loading it in webview works as expected, but it still doesn't work when webview loads my webpage through internet. Is there any issue such as webview cannot load external js from .js files? the webpage that is being loaded uses an external .js file for script and that file includes the call back.
@KishanSadhwani Have you linked WebKit framework in your application? I have no idea why it doesn't work with external .js file. Let me know when you fix this issue. Good luck!
|
2

Okay so the issue in my case was the call to window.webkit.messageHandlers.backHomePage.postMessage(message); was inside the .js file which was loaded externally and I dont really know why it was not being called.

I solved this issue by injecting an overload of the javascript function, keeping the body same as it is in that external .js file, and injected it at the end of the Document.

Thanks to @Andy for suggesting the idea of injecting userScript in the document. This information might come handy if anyone else faces same issue but is not the answer to the question "How to receive callback in ios from javascript?" so @Andy's answer is accepted since it precisely answers the question.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.