Swift WKWebview与JS互调
2021-11-09 本文已影响0人
丹学徒
项目需求:
一. js调用app方法并同步返回值
js端调用方式:
let res = test("helloworld")
js端的关键代码:
let params = JSON.stringify(params)
let data = {
"method": method, // 传入test
"params": params // 传入helloworld
}
// 使用prompt方法传递参数
let res = prompt(JSON.stringify(data))
return res
swift端的代码:
// 1.注册 这种注册是有返回值
webview.configuration.userContentController.addScriptMessageHandler(self, contentWorld: .page, name: "test")
// 2.继承 WKScriptMessageHandlerWithReply 类
extension WebViewController: WKScriptMessageHandler, WKScriptMessageHandlerWithReply{
/// prompt方式 对应js调用prompt("test")
func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
let jsonObj = JSON.init(parseJSON: prompt)
let method = jsonObj["method"].stringValue
let params = jsonObj["params"].stringValue
print(method)
if method == "test" {
let result = self.test(params)
// result就是返回的值
completionHandler(result)
}
else {
completionHandler("")
}
}
}
二. js调用app方法,使用Promise风格返回值
js端调用方式:.then方式
test("helloworld").then(res=>{
console.log("promise ",res)
})
js端的代码:(伪代码)
return new Promise((resolve, reject) => {
if (this.brower() === 'android') {
...
} else if (this.brower() === 'ios') {
if (window.webkit !== undefined) {
params = JSON.stringify(params)
// method是字符串参数
let res = window.webkit.messageHandlers[method]['postMessage'](params)
resolve(res)
} else { reject('40001')}
}
swift端的代码:
// 1.注册 这种注册是有返回值
webview.configuration.userContentController.addScriptMessageHandler(self, contentWorld: .page, name: "test")
// 2.继承 WKScriptMessageHandlerWithReply 类
/// 返回值Handle 可对接js的Promise风格 .then返回的值
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage, replyHandler: @escaping (Any?, String?) -> Void) {
print("传来的方法为", message.name)
print("传来的参数为", message.body)
if message.name == "test" {
let result = self.test(message.body)
replyHandler(result, nil) // first var is success return val, second is err string if error
}
}
三. js调用app方法,用app回调js的方法去返回值
js端调用方式:
test({
params: “helloworld”,
success: res=>{
console.log("test",res)
}
})
js端的关键代码:
test(params) {
window['TestSuccess'] = params.success
// ...省略调用app的方法了
}
swift端的代码:
// 1.注册 这种注册无返回值
webview.configuration.userContentController.add(self, name: "test")
// 2.继承 WKScriptMessageHandler 类
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage, replyHandler: @escaping (Any?, String?) -> Void) {
print("传来的方法为", message.name)
print("传来的参数为", message.body)
if message.name == "test" {
let strRes = self.test(message.body)
// 成功采用回调js方法
webview.evaluateJavaScript("TestSuccess(\(strRes))") { (jsmessage, err) in
print("成功回调\(String(describing: jsmessage)),\(String(describing: err))")
}
}
}
总结:
- 同步返回值 用第一种方法
- 异步返回值 用第三种方法 app回调js方法
- 没有返回值 就不回调js
至于第二种方式,前端写了这种方法只能也去实现。