Swift.WKWebView与Html文件的JS交互

效果图

实现效果:

以最简单的形式与最简单的demo来实现WKWebView与HTML文件的JS交互方式.

包括Swift调用JS方法以及JS调用Swift原生方法.并传递各种类型参数

实现在控制台打印JS中的Console.log内容.


1.添加WeakScriptMessageDelegate文件,用其作为与JS交互时的代理,防止出现ViewController不释放的问题.

import UIKit
import WebKit
///内存管理,使用delegate类防止ViewController不释放
class WeakScriptMessageDelegate: NSObject, WKScriptMessageHandler {
    weak var scriptDelegate: WKScriptMessageHandler?
    init(_ scriptDelegate: WKScriptMessageHandler) {
        self.scriptDelegate = scriptDelegate
        super.init()
    }
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        scriptDelegate?.userContentController(userContentController, didReceive: message)
    }
    deinit {
        print("WeakScriptMessageDelegate is deinit")
    }
}

2.声明WKWebView,并注册与JS交互的名称.

   lazy var webView: WKWebView = {
        ///偏好设置
        let preferences = WKPreferences()
        preferences.javaScriptEnabled = true

        let configuration = WKWebViewConfiguration()
        configuration.preferences = preferences
        configuration.selectionGranularity = WKSelectionGranularity.character
        configuration.userContentController = WKUserContentController()
        // 给webview与swift交互起名字,webview给swift发消息的时候会用到
        configuration.userContentController.add(WeakScriptMessageDelegate(self), name: "logger")
        configuration.userContentController.add(WeakScriptMessageDelegate(self), name: "redResponse")
        configuration.userContentController.add(WeakScriptMessageDelegate(self), name: "blueResponse")
        configuration.userContentController.add(WeakScriptMessageDelegate(self), name: "greenResponse")
        configuration.userContentController.add(WeakScriptMessageDelegate(self), name: "yellowResponse")

        var webView = WKWebView(frame: CGRect(x: 0,
                                              y: 0,
                                              width: UIScreen.main.bounds.width,
                                              height: UIScreen.main.bounds.height),
                                configuration: configuration)
        // 让webview翻动有回弹效果
        webView.scrollView.bounces = false
        // 只允许webview上下滚动
        webView.scrollView.alwaysBounceVertical = true
        webView.navigationDelegate = self
        return webView
    }()

3.Html文件样式

  <!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,user-scalable=no"/>
            </head>
    <body>
        名字:<span id="name"></span>
        <br/>
        <button style = "background-color: #ff0000;color: #FFFFFF;padding: 15px 32px;" onclick="redResponse()">红色</button>
        <button style = "background-color: #0041ff;color: #FFFFFF;padding: 15px 32px;" onclick="blueResponse()">蓝色</button>
        <button style = "background-color: #00d819;color: #FFFFFF;padding: 15px 32px;" onclick="greenResponse()">绿色</button>
        <button style = "background-color: #ffe064;color: #FFFFFF;padding: 15px 32px;" onclick="yellowResponse()">黄色</button>
        <!--   添加这个script在项目头,这样swift才能打印console.log的内容         -->
        <script>
            var console = {};
            console.log = function(message){window.webkit.messageHandlers['logger'].postMessage(message)
            };
        </script>
        <script type="text/javascript">
            ///被swift调用的方法
            function sayHello(text) {
                console.log(text)
            }
        ///调用swift方法的方式 window.webkit.messageHandlers.(swift注册的交互名).postMessage(传给swift的参数)
        function redResponse() {
            ///没有参数传可以传任意值,让swift端不接收
            window.webkit.messageHandlers.redResponse.postMessage("")
        }
        function blueResponse() {
            window.webkit.messageHandlers.blueResponse.postMessage("蓝色")
        }
        function greenResponse() {
            window.webkit.messageHandlers.greenResponse.postMessage(1)
        }
        function yellowResponse() {
            window.webkit.messageHandlers.yellowResponse.postMessage(["1","2","3"])
        }
        </script>
    </body>
</html>

4.实现调用JS方法

让控制器实现WKNavigationDelegate协议

extension ViewController: WKNavigationDelegate{
    ///在网页加载完成时调用js方法
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        webView.evaluateJavaScript("sayHello('js你好,我是从Swift传来的')", completionHandler: nil)
    }
}

5.接收JS调用方法

让控制器实现WKScriptMessageHandler协议

 extension ViewController: WKScriptMessageHandler{
    ///接收js调用方法
    func userContentController(_ userContentController: WKUserContentController,
                               didReceive message: WKScriptMessage) {
        ///在控制台中打印html中console.log的内容,方便调试
        let body = message.body
        if message.name == "logger" {
            print("JS log:\(body)")
            return
        }
        ///message.name是约定好的方法名,message.body是携带的参数
        switch message.name {
        case "redResponse":
            ///不接收参数时直接不处理message.body即可,不用管Html传了什么
            redRequest()
        case "blueResponse":
            blueRequest(string: message.body as! String)
        case "greenResponse":
            greenRequest(int: message.body as! Int)
        case "yellowResponse":
            yellowRequest(array: message.body as! [String])
        default:
            break
        }
    }
}


####截止以上功能已经全部实现,接下来讲一下与h5协同调试时很重要一部分,就是打印出JS方法中console.log的内容,这样才能即时的,直观的了解交互情况.安卓方面自带了这个功能,但是WKWebView需要我们与H5同时添加代码才能够实现.
######1.在html文件中声明console

 <!--   添加这个script在项目头,这样swift才能打印console.log的内容         -->
        <script>
            var console = {};
            console.log = function(message){window.webkit.messageHandlers['logger'].postMessage(message)
            };
        </script>
        <script type="text/javascript">

######2.在swift文件中声明webView时使用configuration注册与JS交互名

configuration.userContentController.add(WeakScriptMessageDelegate(self), name: "logger")

######3.在swift文件中接收方法里添加

 ///接收js调用方法
    func userContentController(_ userContentController: WKUserContentController,
                               didReceive message: WKScriptMessage) {
        ///在控制台中打印html中console.log的内容,方便调试
        let body = message.body
        if message.name == "logger" {
            print("JS log:\(body)")
            return
        }
  }

github地址:WKWebView-Script

使用WKWebView与H5交互还是很简单的,如果需要可以先在本地实现,然后把html文件给做H5的同事参考一下.双方多交流相信可以很快实现.

有问题欢迎探讨.

猜你喜欢

转载自blog.csdn.net/weixin_43566445/article/details/84023176