如何将 swift 对象传递给 javascript (WKWebView / swift)
Posted
技术标签:
【中文标题】如何将 swift 对象传递给 javascript (WKWebView / swift)【英文标题】:How do I pass a swift object to javascript (WKWebView / swift) 【发布时间】:2015-11-13 20:11:06 【问题描述】:我正在将数据从 swift 传递到 WKWebView 中的 javascript
我有一个自定义类:
class AllInfo: AnyObject
var title = "Special Title"
var description = "Special Description"
并用
初始化它var info = AllInfo()
然后我有一个 WKWebView,我通过它传递一个 WKUserScript,我有一个源属性:
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);
编辑:当我尝试访问这样的对象时,我得到了未定义。
所以我的问题是:
我可以将 AnyObject 传递给 JavaScript 并访问它吗? 如果没有,我应该制作什么类型的 swift 类,以便我可以轻松通过它。
我很想在 swift 中创建一个 javascript 对象作为字符串并传递它,但我觉得有更好的方法。
谢谢
编辑:我在下面回答了我如何能够将数据作为 JSON 传递。
【问题讨论】:
【参考方案1】:这是我的建议(使用 json 作为数据示例):
-
创建 json:
var json = ["value1": "一", "value2": "二"]
-
编码为字符串(我没有使用base64):
guard let json = 试试? JSONEncoder().encode(permissionsJSON), 让 jsonString = String(data: json, encoding: .utf8) else 返回
-
发送:
webView.evaluateJavaScript("window.evite.webview.yourName('(jsonString)')")
【讨论】:
【参考方案2】:这是来自 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)")
)
【讨论】:
上面的引号不正确这里是如何传递数据 let script = "getSessionIdUserId('(sessionId)', '(userId)')" self.webView?.evaluateJavaScript(script, completionHandler: (obj:Any?, error:Error?) in )【参考方案3】:将原生对象传递给 javascript 很复杂,尤其是对于在多进程模式下运行的 WKWebView。任何有关本机对象的操作都需要跨越进程边界。 WKWebView 在原生和 javascript 之间没有语言绑定支持。但是,WKWebView 支持消息传递 API。对于 JS 和 native 之间的复杂交互,您必须将其包装起来。
我创建了一个名为XWebView 的项目,它基于 WKWebView 的原始消息传递提供语言绑定样式的 API。它是用 Swift 编写的。
关于您的示例,必须首先将对象注入到 javascript 命名空间中:
let webView = WKWebView(frame: frame, configuration: WKWebViewConfiguration())
webView.loadPlugin(AllInfo(), namespace: "someInfo")
您可以在 javascript 中访问该对象:
console.log(window.someInfo.title);
window.someInfo.title = "Some title";
要将 Swift 对象公开给 javascript,属性和方法必须是动态调度的。这意味着,属性必须是动态的,方法必须具有@objc 属性。 (有关动态调度,请参阅https://developer.apple.com/swift/blog/?id=27)。简单来说,继承自 NSObject。
【讨论】:
看看下面我更简单的解决方案.. 没有 XWebView 或动态调度等【参考方案4】:在.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;
【讨论】:
完美。这很好用。但是我认为这适用于任何 JSON 响应。而不是自定义对象。 @BlackFlam3 你能不能先把自定义对象转成 JSON 对象? @Crashalot 是的,我确实错过了一些东西。所以我发现将 JSON 转换为自定义对象很容易,而且可能我需要编写一个反向函数来将自定义对象转换为 JSON。 如果数据中包含汉字,则此方法无效。不幸的是,atob
无法解码 UTF-8:***.com/questions/30106476/…【参考方案5】:
回答我自己的问题:
JSON 是(可能)传递给 javascript 的最佳类型。
我删除了该类,而是创建了一个类似 NSDictionary 的类(或将您的类键入为 NSDictionary):
var allInfoRawSwift = ["title": "This is the title", "description": "this is the description"]
然后将其转换为 JSON(在 do/catch if swift 2 中):
let allInfoJSON = try NSJSONSerialization.dataWithJSONObject(allInfoRawSwift, options: NSJSONWritingOptions(rawValue: 0))
将 JSON 转换为字符串:
let allInfoJSONString = NSString(data: allInfoJSON, encoding: NSUTF8StringEncoding)!
然后添加源属性,如:
source: "changeDisplay(\(allInfoJSONSting))"
要进行调试,最好让您的函数为您传递的任何内容设置一个全局变量,然后使用 safari 的开发人员模式访问 Web 控制台并检查全局变量。
如果有更好的方法或者您有任何提示,请告诉我。
谢谢
【讨论】:
以上是关于如何将 swift 对象传递给 javascript (WKWebView / swift)的主要内容,如果未能解决你的问题,请参考以下文章
如何将 NSData 参数传递给在 swift 3 中调用的目标 c 方法?
iOS Swift 如何从 UIWebView 将 JSON 字符串和数组或字典传递给 Javascript?
使用 UITapGestureRecognizer、UIImageView 和 UITableViewCell 将参数传递给 Swift 中的选择器