1

I want to call a swift function from java script code which returns the device id back to the script, I had added the code that use currently. Please advise how to return the value back to the java script from the swift function, Thanks in advance

Code Snippet :

     super.viewDidLoad()
    {
    self.webView = WKWebView()
    let preferences = WKPreferences()
    preferences.javaScriptEnabled = true
    let configuration = WKWebViewConfiguration()
    configuration.preferences = preferences
    configuration.userContentController = contentController
    configuration.userContentController.addScriptMessageHandler(self,name: "interOp")
    self.webView = WKWebView(frame: self.view.frame, configuration: configuration)
    print(self.view.frame)
    self.view = self.webView
    webView!.navigationDelegate = self
    let url = NSURL(string:"http://softence.com/devTest/vb_ios.html")
    let req = NSURLRequest(URL:url!)
    self.webView!.loadRequest(req)

    }

// did receivescript message is working fine
func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage)
{
    let sentData = message.body as! NSDictionary
    print(sentData)
    if sentData["name"] as! String == "DeviceInfo"
    {
        self.DeviceInfo()
    }
}
// i want to return the following device info to javascript
func DeviceInfo() -> String
{
let dict = NSMutableDictionary()
    dict.setValue(UIDevice.currentDevice().model, forKey: "model")
    dict.setValue(UIDevice.currentDevice().name, forKey: "name")
    dict.setValue(UIDevice.currentDevice().systemVersion, forKey: "system_version")
    return String(dict)
}
Janmenjaya
  • 4,149
  • 1
  • 23
  • 43
Mohanraj
  • 587
  • 4
  • 21

1 Answers1

2

Try having a look at the evaluateJavaScript(_:, completionHandler:) function on WKWebView as described here

To use that, your DeviceInfo function should define the complete JavaScript string which you would like to execute.

So for instance if you had a JavaScript function defined like so:

showDeviceInfo(model, name, system_version) {

}

Then your DeviceInfo function could look something like this:

func deviceInfo() {
    let model = UIDevice.currentDevice().model
    let name = UIDevice.currentDevice().name
    let systemVersion = UIDevice.currentDevice().systemVersion

    let javaScriptString = "showDeviceInfo(\(model), \(name), \(systemVersion));" //string your JavaScript string together from the previous info...and no...it aint pretty :)
    webView.evaluateJavaScript(javaScriptString, completionHandler: nil)
}

You could also return javaScriptString from your DeviceInfo function and then call it in your userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage), the important things are:

  1. you need to define the entire JavaScript string you would like to execute
  2. you need to call evaluateJavaScript

Hope that helps you.

pbodsk
  • 6,787
  • 3
  • 21
  • 51
  • hi thanks for your reply... i tried sending a simple string through evaluateJavaScript method, but nothing is reflected and shows 'undefined' in the web page. And also i dont want to send the data, java script has to call the swift function automatiically and get the value returned from the swift function @pbodsk – Mohanraj Sep 22 '16 at 10:19
  • what did the string you sent look like? It has to be valid JavaScript. About "JavaScript has to call the swift function automatically", it is, isn't it? You call the Swift function from your JavaScript which calls `didReceiveScriptMessage`. That again calls `deviceInfo()` that will generate a JavaScript string which calls your JavaScript function, filled with the correct data. Or am I misunderstanding what you mean? Hope I'm making sense – pbodsk Sep 22 '16 at 10:52
  • yeah you are correct I'm asking whether we can call the swift function directly from the java script code without sending a message to the swift code as like in android. – Mohanraj Sep 22 '16 at 11:12
  • As I understand it, you can not, you have to use the `WKUserContentController` as a sort of bridge between your JavaScript code and your native code, as you've set up in your example above. Once you call `window.webkit.messageHandlers.interOp.postMessage(someDataHere);` that is detected by your `WKUserContentController` and `didReceiveScriptMessage` is called, giving you the possibility to figure out exactly which JavaScript function was called. To send data the other way, you can use the method I've tried to describe above – pbodsk Sep 22 '16 at 11:24
  • have a look at this article: http://www.priyaontech.com/2014/12/native-–-js-bridging-on-ios8-using-wkwebview/ or this one http://nshipster.com/wkwebkit/ hope they can help you understand whats going on :) – pbodsk Sep 22 '16 at 11:29
  • One more... what is the use of WKUserScript* userScript = [[WKUserScriptalloc]initWithSource:js injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:NO]; [userController addUserScript:userScript]; as i had not included it in my code... Can u advice about this – Mohanraj Sep 22 '16 at 12:05
  • It seems to be "local/native" JavaScript, by which I mean JavaScript that you have in your app and which you can then inject into the content of your `WKWebView`. So for instance if you would like to make all `

    ` tags yellow in your app (for some odd reason!), you could make a script that would do that and then inject that into your `WKWebView` at some point. You can see the description here: https://developer.apple.com/reference/webkit/wkuserscript I haven't used this though, but maybe it can help you.

    – pbodsk Sep 22 '16 at 12:13