Yessen Yermukhanbet
Yessen Yermukhanbet

Reputation: 105

Call native swift function in javascript

I am sorry, if this question was already asked, but all the answers I could find are for complicated solutions.

I have a viewController, which is webView. I added WKWebView, to my view from WebKit library, and opened simple url. Inside of my ViewController, I have a native function called showAd. When the user press the button, which was implemented in javascript, it show call showRewardsAd. I set the break point to the userContentController, however, it never goes there.

func showAd(){
   print("invoked")
}
extension WFWebViewController: WKScriptMessageHandler{
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "showRewardsAd"{
            self.showRewards()
            webView.evaluateJavaScript("test", completionHandler: nil)
        }
    }
}

My goal is to simply allow this function to be called from javascript part. As I know, if I want to call javascript function in swift, I simply have to say:

 webview.addJavascriptInterface('javascript: function_name();')

However, in my case, I want to do it in reverse order. Call swift function in Javascript code.

Upvotes: 5

Views: 5804

Answers (1)

Starsky
Starsky

Reputation: 2048

You need to inject your user script inside the webView so you could listen to JavaScript's messages when they are posted.

Firstly, you will need to initialize the webView's config and preferences, to allow javaScript:

let config = WKWebViewConfiguration()
let preferences = WKPreferences()
preferences.javaScriptEnabled = true
config.preferences = preferences

Now, you need to inject your script to listen for the click events from the webView:

let userController = WKUserContentController()
let javaScript = "showRewardsAd = function() {\n" + "window.webkit.messageHandlers.adClicked.postMessage(); }"
let script = WKUserScript(source: javaScript, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
userController.addUserScript(script)
userController.add(self, name: "adClicked")
config.userContentController = userController

Now instantiate your webView with the configuration from above:

self.webView = WKWebView(frame: .zero, configuration: config)

Now, your WKScriptMessageHandler protocol is implemented correctly:

extension WFWebViewController: WKScriptMessageHandler{
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "showRewardsAd"{
            self.showRewards()
            print("Ad is being shown.")
        }
    }
}

I hope this works for you. I assumed that showRewardsAd is implemented in the JavaScript on the website which you're accessing.

Upvotes: 4

Related Questions