當前環境: 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
瞭解 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")
}
複製代碼
瞭解 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
這個庫,是由於它可以知足咱們開發的大部分場景,是基於WKWebView
實現JSBridge
的比較好的實現,那麼咱們就看看它的工做原理是什麼,這樣也有助於咱們使用這種庫。
咱們只會針對其中的兩種方法進行研究其原理 ,若是你沒使用過能夠去看下再回來可能會更好。DSBridge-IOS
下面是DSBridge
與Native
交互的兩種方式: 一種是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的通訊能力,再來藉助一下動態運行時來完成,雖然外表看起來神祕,可是通過源碼閱讀後,會發現其實仍是很簡單的。 以上所有是原做,若有建議和提議,不妨在下面留言,但願能對一些朋友有所幫助。