JS 传递参数到 Native
前面完成了 JS 调用 Native,接下来继续 JS 如何传递参数到 Native
传递原始类型数据
先看 JS 端的代码:
function onClickButton() {
window.webkit.messageHandlers.iOSBridge.postMessage("Hello");
}
postMessage时传递了Hello字符串,再看 Native 如何接收:
func userContentController(
_ userContentController: WKUserContentController,
didReceive message: WKScriptMessage)
{
// postMessage传递的参数可以通过message.body拿到,但需要转换成Swift的String
let body = message.body as! String
// 打印一下
print("WebView callNative ok. body is \(body)")
}
运行后,打印的结果:
WebView callNative ok. body is Hello
传递 json 对象
window.webkit.messageHandlers.iOSBridge.postMessage({
name: "mingo"
});
Native:
// 将body转换为Swift的字典结构
let body = message.body as! [String : Any]
print("WebView callNative ok. body is \(body)")
print("WebView arg name=\(body["name"]!)")
输出:
WebView callNative ok. body is ["name": mingo]
WebView arg name=mingo
JS 传递参数到 Native 只能传递原始数据类型,JSON 里也只能包含原始数据类型 Function/Class 之类的是不能传递到 Native 的,因此他们之间实际是信息交 换,而不是同一语言的调用关系。
Native 返回结果给 JS
首先要明确的是:Native 没有任何方式“直接返回”结果给 JS,至少 iOS 的 WKWebView 是这样的。 但是 Native 可以运行一段 JS 代码:
webView.evaluateJavaScript("console.log('log from native')") { _, _ in }
我们通过 webView 的evaluateJavaScript方法,运行了 JS:
console.log("log from native");
所以我们利用这个功能实现结果返回,来看看 Native 怎么写:
class ViewController: UIViewController, WKUIDelegate {
var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let config = WKWebViewConfiguration()
// 声明变量,而不是直接在下一行创建
let birdge = BridgeHandler()
config.userContentController.add(birdge, name: "iOSBridge")
webView = WKWebView(frame: self.view.frame, configuration: config)
webView.uiDelegate = self
self.view.addSubview(webView)
// 赋值webView给BridgeHandler
birdge.webView = webView
let url = Bundle.main.url(forResource: "test", withExtension: "html")!
webView.loadFileURL(url, allowingReadAccessTo: url)
}
}
class BridgeHandler : NSObject, WKScriptMessageHandler {
var webView: WKWebView!
func userContentController(
_ userContentController: WKUserContentController,
didReceive message: WKScriptMessage)
{
let body = message.body as! [String: Any]
print("WebView callNative ok. body is \(body)")
print("WebView arg name=\(body["name"]!)")
// 在收到js调用后运行以下代码
webView.evaluateJavaScript("onNativeResult('Native callback ok.')") { _, _ in }
}
}
JS 端做好接收返回的代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<style type="text/css">
html,
body {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
button {
display: block;
width: 100%;
height: 30%;
font-size: 50px;
}
/* 字体放大点 */
pre {
font-size: 40px;
}
</style>
</head>
<body>
<script type="text/javascript">
function onClickButton() {
window.webkit.messageHandlers.iOSBridge.postMessage({
name: "mingo"
});
}
// 声明一个方法给Native运行
function onNativeResult(result) {
var logEl = document.getElementById("log");
logEl.innerText += result + "\n";
}
</script>
<!-- 打算点击按钮调用native -->
<button onclick="onClickButton()">Call Native</button>
<pre id="log">
<!-- 用于显示js的日子 -->
</pre>
</body>
</html>
运行后,点击几次按钮得到的结果:
到这里已经完成了 Native 返回结果给 JS 端了。