如何實現JSBridge基於WKWebView

當前環境: Xcode10.0 Swift4.2 iOS SDK 12.1ios

下面是原理實現代碼,能夠查看參考文章 + Demo查看。 Demo: github.com/zColdWater/…git

前提掌握

背景概述: 隨着App端H5的應用愈來愈多,H5同窗會遇到與Native同窗同樣的Native需求,那麼這個時候就須要 Native同窗 與 H5同窗能進行 通訊了,那麼爲基於iOS的WKWebView該如何找到正確通訊方式呢?github

在這裏咱們參考 DSBridge-IOS,固然若是你已經看過這個庫的源碼,那麼此篇文章能夠跳過了。我這裏會根據DSBridge的源碼介紹下它的JSBridge的實踐web

關於WKWebView一些必要的方法使用能夠點擊這裏api

  1. 瞭解 Javascript ===[調用]===> Native異步

    如何實現 Javascript 調用 Native 呢? 其實Apple已經提供了這個通道 ,這個通道就是WKUIDelegate,若是還不清楚能夠點擊這裏查看函數

    這裏咱們只提WKUIDelegate中的其中的一個方法,至於爲何選用這個回調方法,緣由是由於 這個通道 可讓Javascript傳遞二個參數,而且還能獲得一個同步的返回值。ui

    // Javascript 調用 prompt 方法 會觸發 這個代理方法 
    // 例如: var result = prompt("AA", "BB")
    func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
        // 參數1 
        var param1 = prompt //"AA"
        // 參數2
        var param2 = defaultText // "BB"
        // 回調 result
        completionHandler("同步返回值 給Javascript")
    }
    複製代碼
  2. 瞭解 Native ===[調用]===> Javascriptlua

    如何實現 Native 調用 Javascript 的方法呢,Apple一樣也給咱們提供了通道, 這個通道就是evaluateJavaScript方法,若是你還不瞭解,若是還不清楚能夠點擊這裏查看spa

    咱們事先準備好 JS方法 nativeMessageHandler 而後在代碼中 找到一個時機, 調用便可 觸發Javascript方法

    function nativeMessageHandler(method,param) {
        // 'action1','param1'
        console.log(method,param) 
    }
    複製代碼
    // Native 代碼
    
    // 注意: 此方法 只有在整個WebView都加載完成 纔會有反應。
    webview.evaluateJavaScript("nativeMessageHandler('action1', 'param1')", completionHandler: { (feedback, error) in
    })
    複製代碼

瞭解DSBridge-IOS原理

下面是純乾貨了,至於爲何咱們研究DSBridge-IOS這個庫,是由於它可以知足咱們開發的大部分場景,是基於WKWebView實現JSBridge的比較好的實現,那麼咱們就看看它的工做原理是什麼,這樣也有助於咱們使用這種庫。

咱們只會針對其中的兩種方法進行研究其原理 ,若是你沒使用過能夠去看下再回來可能會更好。DSBridge-IOS

下面是DSBridgeNative交互的兩種方式: 一種是JS調用Native方法,另外一種是Native調用JS方法

1. 同步調用 使用DSBridge第三方以下: ```Javascript // 同步 調用 function callSyn() {

// 對應原生方法名: `testSyn`
    // 參數: `Hello` 
    // 類型: 同步調用
    dsBridge.call("testSyn", "Hello")
}
```
**實現原理**: 在`DSBridge`裏面是經過[`WKUIDelegate`](https://zcoldwater.github.io/blog/article/ios/wkwebview/)去實現同步調用的,JS會經過調用`prompt`方法,喚起`Native`層的`WKUIDelegate`代理協議中的下面的方法 
```Swift
func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
}
```
而後這個協議回調方法裏面,經過`JS`給`Native`的類名,方法名,經過OC的Runtime去動態的調用此方法,獲得返回值,而且返回給回調函數`completionHandler` 實現`Native`返回值給`JS`方法。
複製代碼

2. 異步調用 使用DSBridge第三方以下: ```Javascript // 異步 調用 function callAsyn() {

// 對應原生方法名: `testAsyn`
    // 參數: `hello`
    // 類型: 異步調用
    dsBridge.call("testAsyn","hello", function (value) {
        // 獲得原生回調 參數。
        console.log(value)
    })
}
```
**實現原理**: 在`DSBridge`裏面是經過[`WKUIDelegate`](https://zcoldwater.github.io/blog/article/ios/wkwebview/)和`evaluateJavaScript`方法來實現的`JS`調用`Native`而後`Native`回調給`JS`的。 
首先,`JS`方法調用`Native`附加回調參數,`JS`會把這個回調函數註冊在`JS`全局下,好比說,掛在全局叫`BlockA`,而後繼續經過調用`prompt`方法觸發`WKUIDelegate`協議回調,方法在下面。
```Swift
func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
}
```
而後在拿到`WKUIDelegate`的回調後,`Native`還會經過傳來類名,方法名,根據OC Runtime去動態調用方法,而後拿到同步返回值,給`completionHandler`方法調用,返回給JS,當經過Runtime動態調用到`Native`方法內的時候,咱們觸發回調參數,來回調給`JS`,這步就須要方法`evaluateJavaScript`來實現,由於當初咱們掛在整個`JS`下有一個回調函數,而且起了名,如今就須要回調給寫調用`JS`這個全局的回調,而且把結果告知給它。
複製代碼

下面是總體流程圖:

總結

上面咱們分析了實現方式,無非都是用系統提供的與JS的通訊能力,再來藉助一下動態運行時來完成,雖然外表看起來神祕,可是通過源碼閱讀後,會發現其實仍是很簡單的。 以上所有是原做,若有建議和提議,不妨在下面留言,但願能對一些朋友有所幫助。

相關文章
相關標籤/搜索