Reputation: 253
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
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
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
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