swift2 如何将swift对象传递给javascript(WKWebView / swift)

zqry0prt  于 2022-11-06  发布在  Swift
关注(0)|答案(5)|浏览(208)

我正在WKWebView中将数据从swift传递到javascript
我有一个自定义类:

class AllInfo: AnyObject {
    var title = "Special Title"
    var description = "Special Description"
}

并初始化为

var info = AllInfo()

然后,我有一个WKWebView,通过它我传递了一个WKUserScript,通过它我有一个source属性:

source: "changeDisplay('\(info)')"

我的问题是如何在javascript中访问这个对象。我尝试过像访问javascript对象一样访问它,也尝试过像访问关联数组一样访问它,但没有成功。下面是js函数:

function changeDisplay(passedInfo) {
    document.querySelector('h1').innerHTML = passedInfo.title
    document.querySelector('h2').innerHTML = passedInfo.description
}
setTimeout(function () {changeDisplay();}, 5000);

EDIT:当我试图像这样访问对象时,我得到了未定义的结果。
所以我的问题是:

我可以将AnyObject传递给JavaScript并访问它吗?如果不能,我应该将swift类设置为什么类型,以便可以轻松传递它。

我很想在swift中创建一个字符串形式的javascript对象,然后传递它,但我觉得还有更好的方法。
谢谢
编辑:我在下面回答了我如何能够以JSON形式传递数据。

oxosxuxt

oxosxuxt1#

在.swift中,定义并调用此方法。

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)")
    }
}

在.js/.html文件中

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;
}
z18hc3ub

z18hc3ub2#

将原生对象传递给javascript比较复杂,尤其是对于多进程模式下运行的WKWebView,任何关于原生对象的操作都需要跨越进程边界,WKWebView没有提供原生和javascript之间的语言绑定支持,但是WKWebView支持消息传递API,为了实现JS和原生之间的复杂交互,需要对其进行 Package 。
我创建了一个名为XWebView的项目,它基于WKWebView的原始消息传递提供了语言绑定风格的API。
对于您的示例,必须首先将对象注入javascript名称空间:

let webView = WKWebView(frame: frame, configuration: WKWebViewConfiguration())
webView.loadPlugin(AllInfo(), namespace: "someInfo")

您可以在javascript中访问该对象:

console.log(window.someInfo.title);
window.someInfo.title = "Some title";

要向JavaScript公开Swift对象,属性和方法必须是动态调度的。这意味着,属性必须是 dynamic,方法必须具有 @objc 属性。(有关动态调度,请参阅https://developer.apple.com/swift/blog/?id=27)。简单来说,从NSObject继承。

utugiqy6

utugiqy63#

回答我自己的问题:
JSON(可能)是传递给javascript的最佳类型。
我删除了这个类,并创建了一个NSDictionary,如下所示(或者将您的类键入为NSDictionary):

var allInfoRawSwift = ["title": "This is the title", "description": "this is the description"]

然后将其转换为JSON(如果是swift 2,则在do/catch内):

let allInfoJSON = try NSJSONSerialization.dataWithJSONObject(allInfoRawSwift, options: NSJSONWritingOptions(rawValue: 0))

将JSON转换为字符串:

let allInfoJSONString = NSString(data: allInfoJSON, encoding: NSUTF8StringEncoding)!

然后添加源属性,如:

source: "changeDisplay(\(allInfoJSONSting))"

要进行调试,最好让您的函数将全局变量设置为您传递的任何值,然后使用safari的开发者模式访问Web控制台并检查全局变量。
如果有更好的方法或者你有什么建议就告诉我。
谢谢

qcuzuvrc

qcuzuvrc4#

以下是从Ashok接受的答案更新的Swift代码,与Swift 3.0.2兼容:

func evaluateJavaScriptForData(dictionaryData: [String: AnyObject]) {
    // Convert swift dictionary into encoded json
    let serializedData = try! JSONSerialization.data(withJSONObject: swiftObject, options: .prettyPrinted)
    let encodedData = serializedData.base64EncodedString(options: .endLineWithLineFeed)
    // This WKWebView API to calls 'reloadData' function defined in js
    webView.evaluateJavaScript("reloadData('\(encodedData)')", completionHandler: { result, error in
        print("Completed Javascript evaluation.")
        print("Result: \(result)")
        print("Error: \(error)")
    })
}
unftdfkk

unftdfkk5#

下面是我的建议(使用json作为数据示例):
1.创建json:
变量json = [“值1”:“一”,“值2”:“两个”]
1.编码为字符串(我没有使用base64):
如果你想在一个简单的例子中使用一个字符串,那么你可以使用一个字符串来表示你的数据。json,编码:. utf8)否则{ return }
1.发送日期:
“窗口名称"('jsonString。')”)

相关问题