这几乎是WKWebview使用者的一大痛了,前提是当你不懂Javascript的时候,你压根不知道这个怎么玩。
原因是WKWebview并不是完全不能向Javascript传参,理论上是可以的,Swift提供了两个通道和Javascript进行交互:

  1. 实现WKScriptMessageHandler协议对Javascript的调用进行监听
  2. 使用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对我执行的是另一个函数,这样就会出现两个问题:

  1. 一个请求方法对应一个回调方法,程序结构上太繁琐
  2. 代码不在同一个函数里,变量没办法公用,势必要进行全局化或者临时存储,导致逻辑繁琐

那么,有没有方法可以实现直接回调呢?哪里请求就在哪处理?答案是肯定的。
下面就交给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的内容,说明数据已经回调成功了。
以上。