Korken55
Korken55

Reputation: 253

Calling swift Code From Javascript

Is it possible to call Swift functions/callbacks from Javascript ? In Android it is possible to use JavaVoidCallbacks, is there anything similar in Swift? Right now Im using JavaScriptCore,where i can call javascript functions from Swift.

Upvotes: 4

Views: 6583

Answers (3)

epx
epx

Reputation: 1096

In Swift, the easiest way I found was to create a gateway object in Javascript, using e.g. evaluateScript(), and then adding functions to that object:

let gateway = jsContext.objectForKeyedSubscript("gateway" as NSString)
let p: @convention(block) (Int, Double) -> () = { h, ms in
     return self.swift_method(h, ms)
}
gateway!.setObject(p, forKeyedSubscript: "swift_method" as NSString)

After that you can call gateway.swift_method() in Javascript.

Most type conversions are automatic. I have used types Int, Double, String and [Int] as parameter and/or return types in the lambda.

Upvotes: 0

David.Chu.ca
David.Chu.ca

Reputation: 38664

I have the same question. When I saw the answers to this Q. I tried to use JavaScriptCore to call Swift methods from the JS side. I could inject Swift or JS methods into JSContext. However, the methods injected into JSContext are not accessible in my case.

I use WKWebView as an HTML viewer in the ViewController in my iOS native app. I use this kind of view controller to present some help information in my app. After several days of struggling, I finally found an alternative way to make Swift and JS interaction happen. The strategy is to use WKScriptMessageHandler as a gateway between Swift and JS. Refer to this good blog on how to do it in detail. Another blog, Using WebKit to call WKWebView JavaScript from Swift and Swift from JavaScript, provides another example case, which is very useful.

From my experience, WKScriptMessageHandler is based on a very elegant structure. Through WKUserContentController, you set up a message gateway between JS and Swift. There is This will allow a JS callback to Swift with messages. A delegate of WKWebViewConfiguration has to be implemented, my view controller with web view, or my custom class, to receive JS message calls with data. The message can take a JSON string as a parameter to pass data. On the Swift side, by using a similar JSContext syntax like evaluateJavaScript to specify JS a function with data.

By the way, I was told that in my case, JavaScriptCore is based on Java virtue machine. There may be performance issue and may pose a security risk. Apple has disabled the feature of JavaScriptCore in WKWebView.

The Xcode in my case is Version 13.4, and Swift is 5.

I have written a blog on this: Build a Bridge between Swift and JS

Upvotes: 1

Giuseppe Lanza
Giuseppe Lanza

Reputation: 3699

Yes you can.

Please refer to this Tutorial: https://www.raywenderlich.com/124075/javascriptcore-tutorial

You are interested in the paragraph "Exposing Native Code"

In obj-c is very simple. You can do it just by using your jsContext as a normal dictionary.

context[@"functionName"] = ^ <#returnType#> (<#parameters#>) {
    <#Your code#>
}

Hope it helped.

Upvotes: 4

Related Questions