I am working on passing data from swift to javascript inside a WKWebView
I have a custom class:
class AllInfo: AnyObject {
var title = "Special Title"
var description = "Special Description"
}
and initialize it with
var info = AllInfo()
I then have a WKWebView with which i pass a WKUserScript with which I have a source property of:
source: "changeDisplay('\(info)')"
My problem is how do I access this object in the javascript. I have attempted to access it like a javascript object as well as associative array with no luck. Here's the js funciton:
function changeDisplay(passedInfo) {
document.querySelector('h1').innerHTML = passedInfo.title
document.querySelector('h2').innerHTML = passedInfo.description
}
setTimeout(function () {changeDisplay();}, 5000);
EDIT: When I do attempt to access the object like this, I get undefined.
So my questions are:
Can I pass an AnyObject to JavaScript and access it? If not, what type should I make the swift class so that I can easily pass it.
I am tempted to just create a javascript object in swift as a string and pass that, but I feel there's a better way.
Thanks
EDIT: I answered how I was able to pass data as JSON below.
A WKWebView object is a platform-native view that you use to incorporate web content seamlessly into your app's UI. A web view supports a full web-browsing experience, and presents HTML, CSS, and JavaScript content alongside your app's native views.
Passing a native object to javascript is complex, especially for WKWebView which runs in multi-process mode. Any operation regarding the native object needs to cross process boundary. WKWebView has no language binding support between native and javascript. However, WKWebView supports message passing API. You have to wrap it for complex interactions between JS and native.
I created a project named XWebView which provides language binding styled API based on the raw message passing of WKWebView. It's written in Swift.
Regarding your example, the object has to be injected in javascript namespace firstly:
let webView = WKWebView(frame: frame, configuration: WKWebViewConfiguration())
webView.loadPlugin(AllInfo(), namespace: "someInfo")
You can access the object in javascript:
console.log(window.someInfo.title);
window.someInfo.title = "Some title";
To expose an Swift object to javascript, properties and methods must be dynamic dispatching. This means, properties must be dynamic, methods must has @objc attribute. (See https://developer.apple.com/swift/blog/?id=27 for dynamic dispatching). For simple, inherit from NSObject.
In .swift, define and call this method
func evaluateJavaScriptForData(dictionaryData: [String: AnyObject]) {
// Convert swift dictionary into encoded json
let serializedData = try! NSJSONSerialization.dataWithJSONObject(dictionaryData, options: .PrettyPrinted)
let encodedData = serializedData.base64EncodedStringWithOptions(.EncodingEndLineWithLineFeed)
// This WKWebView API to calls 'reloadData' function defined in js
webView.evaluateJavaScript("reloadData('\(encodedData)')") { (object: AnyObject?, error: NSError?) -> Void in
print("completed with \(object)")
}
}
In .js/.html file
function reloadData(sBinaryParam) {
// This 'atob' decodes the Base64 encoded data sent by swift
var sDecodedParam = window.atob(sBinaryParam);
var oData = JSON.parse(sDecodedParam);
// This 'oData' is your js object (dictionary)
return true;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With