1. 程式人生 > >Swift.WKWebView與Html檔案的JS互動

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
        }
  }

使用WKWebView與H5互動還是很簡單的,如果需要可以先在本地實現,然後把html檔案給做H5的同事參考一下.雙方多交流相信可以很快實現.

有問題歡迎探討.