1

I am developing an ios application that uses WKWebview to display my web application. I have a simple button in my frontend which send the message to WKWebview via window.webkit.messageHandlers.isLocationPresent.postMessage("checkLocation").

IOS Swift

In my viewDidLoad

let configuration = WKWebViewConfiguration()
 let controller = WKUserContentController()

// name of handler called from js code
controller.add(self,name: "isLocationPresent")
configuration.userContentController = controller

let webView = WKWebView(frame: self.view.frame,configuration:configuration)

On ios side I have implemented the userContentController via

func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { 
  if message.name == "isLocationPresent" {
// my logic for checking if location service is available
// if location is present the method returns true else false
  let isGpsAvailable:Bool = self.checkLocationServiceState()
        if isGpsAvailable {
            webView.evaluateJavaScript("sendComment(\(isGpsAvailable ))", completionHandler: {(result,error) in
                print(result)
                print(error)
            })
        }
      else{
           // perform other logic there 
         } 
     }
}

Javascript

 document.getElementById('click').onclick = function() {
    window.webkit.messageHandlers.isLocationPresent.postMessage("checkLocation").
}

function sendComment(aval) {
if(aval) {
  makeRequest()
}
else {
// logic to handle if false
}
}

But everytime i click the button, the evaluateJavascript always throws Javascript Reference error : variable sendComment not found.

The web app is dynamic, each html element is created by javascript. I have three views, when user clicks on a list, he goes to second view, where click button is rendered.

So, calling webview when page loads will not work, because the button element is not rendered in my first view

sendComment() function should only be called by ios when , button is clicked on frontend. I have other use cases also, where the function call should take place in ios when user performs the action in frontend only.

shikhar
  • 174
  • 1
  • 11

2 Answers2

0

Use this code to call js function in Objectiv-C

 NSString * scriptSource = [NSString stringWithFormat:@"sendComment(%@)",msg];
[_WebView evaluateJavaScript:scriptSource completionHandler:^(NSString *result, NSError *error)
 {
     if(result != nil){
         NSLog(@"Result: %@",result);
     }

 }];

Swift:

var scriptSource = "sendComment(\(msg))"
webView.evaluateJavaScript(scriptSource) { (result, error) in
    if result != nil {
        print(result)
    }
}
Vikash Kumar
  • 642
  • 1
  • 11
  • 25
0

I finally solved the issue

Problem

I was implementing my configuration and controller in view.didLoad() func.

Solution

Add all the configuration , preferences and userContentController in loadView() func and load webview either by https endpoint or your local html file in viewDidLoad() func


Load View

override func loadView() {
    super.loadView()

    let preferences = WKPreferences()
    preferences.javaScriptEnabled = true

    let configuration = WKWebViewConfiguration()
    configuration.preferences = preferences

    let userContentController = WKUserContentController()

    userContentController.add(self,name:"sendComment")

    configuration.userContentController = userContentController



    self.view.addSubview(webView)
    self.view.sendSubviewToBack(webView)

    webView = WKWebView(frame: view.bounds, configuration: configuration)

    view = webView
}

View Did Load

Here is my override func viewDidLoad()

override func viewDidLoad() {
        super.viewDidLoad()
        print("view will load")
        // Do any additional setup after loading the view, typically from a nib.

        let request = URLRequest(url:URL(string:"your-url")!)
        webView.navigationDelegate = self

        webView.load(request)
    }

userContentController

My userContentController for receiving JS messages inside the viewController class

    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
            print(message.name)
            if message.name == "sendComment" {
              let result:String = "Marlboro"

                webView.evaluateJavascript("sendComment('\(result)')", completionHandler:{(result , error) in
            if error == nil {
               print("success")
            } 
           else {
             print("error in executing js ", error)
            }
     })
   }
}
shikhar
  • 174
  • 1
  • 11
  • Hi, I got that log: error in executing js Optional(Error Domain=WKErrorDomain Code=4 "A JavaScript exception occurred" UserInfo={WKJavaScriptExceptionLineNumber=0, WKJavaScriptExceptionMessage=TypeError: undefined is not a function, WKJavaScriptExceptionColumnNumber=0, NSLocalizedDescription=A JavaScript exception occurred}) when I am trying to evaluateJavaScript. Pls help me! – Quang Dai Ngo May 08 '19 at 03:05