这几乎是WKWebview使用者的一大痛了,前提是当你不懂Javascript的时候,你压根不知道这个怎么玩。
原因是WKWebview并不是完全不能向Javascript传参,理论上是可以的,Swift提供了两个通道和Javascript进行交互:
- 实现
WKScriptMessageHandler
协议对Javascript的调用进行监听 - 使用
evaluateJavaScript
方法执行Javascript的方法
当我们使用WKScriptMessageHandler
对Javascript的调用进行监听的时候,将通信桥注入到Javascript里
let config: WKWebViewConfiguration = WKWebViewConfiguration()
config.userContentController = WKUserContentController()
config.userContentController.add(self, name: "WebBridge")
这样Javascript端就可以调用这个方法
window.webkit.messageHandlers.WebBridge.postMessage()
同时,可以通过这个方法传递参数
window.webkit.messageHandlers.WebBridge.postMessage({
method: "postToSwift"
})
然后在Swift端实现WKScriptMessageHandler
协议
extension ViewController: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
var param: Dictionary = message.body as! Dictionary<String, Any>
print("\(param["method"])")
}
}
这样就可以针对传递过来的参数method
进行针对的处理
这并没有什么难的,基本网上各种百度就能得到答案,麻烦就麻烦在返回数据上。当你在Javascript端对Swift进行了调用,那么Swift可以很容易拿到参数然后进行相应处理,但是处理后如果要返回数据咋办?直接使用evaluateJavaScript
进行调用?没错,可以是可以,但是这一系列操作都是异步的,当我请求了Swift的之后,Swift对我执行的是另一个函数,这样就会出现两个问题:
- 一个请求方法对应一个回调方法,程序结构上太繁琐
- 代码不在同一个函数里,变量没办法公用,势必要进行全局化或者临时存储,导致逻辑繁琐
那么,有没有方法可以实现直接回调呢?哪里请求就在哪处理?答案是肯定的。
下面就交给Javascript处理吧。
我们先定义一个公用的调用方法
var SwiftPost = function() {
};
SwiftPost.prototype.postToSwift = function(callback) {
//callback是回调函数,在调用的时候定义,然后将函数赋值给预定的回调方法,这样当Swift调用SwiftPostCallback的时候,相当于执行了你传进来的callback这个回调方法,这样就可以实现哪来的回哪去了。
SwiftPostCallback = callback;
this.param = {
method: "postToSwift"
};
return this;
}
SwiftPost.prototype.send = function() {
window.webkit.messageHandlers.WebBridge.postMessage(this.param)
}
var SwiftPostCallback = function(){};
然后调用的时候这样写:
var sp = new SwiftPost();
sp.postToSwift(function(res) {
console.log(res);
}).send();
这样就成功地向Swift发送了请求,接下来是让Swift进行数据回调:
extension ViewController: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
var param: Dictionary = message.body as! Dictionary<String, Any>
switch (param["method"] as! String) {
case "postToSwift":
// wv是WKWebview的变量名
self.wv.evaluateJavaScript("javascript:SwiftPostCallback('you get data')") { (val, error) in
print(error.debugDescription)
}
break
default:
break
}
}
}
执行以下你会发现你的Console里面出现了you get data
的内容,说明数据已经回调成功了。
以上。