Native和JS交互方案選擇

(一)通過URL傳遞函數(shù)名稱和參數(shù)

這個方案是歷史最悠久,至少目前也是使用最普遍的方案。這個方案的優(yōu)點(diǎn)是技術(shù)最簡單,通過scheme://host?query的形式由url來傳遞,iOS和Android都可以用最基礎(chǔ)的方式來實(shí)現(xiàn)俭尖。
當(dāng)然這里還是有一個比較有名的第三方庫WebViewJavascriptBridge不過用這個庫,需要JS洞翩、iOS稽犁、Android三方要協(xié)調(diào)好,最好都要用它骚亿。最后的使用接口還是簡單清晰的已亥。同時支持UIWebView和WKWebView,這種與時俱進(jìn)的做法還是值得提倡来屠。

Native調(diào)JS

  • UIWebView - (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;

  • WKWebView - (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ __nullable)(__nullable id, NSError * __nullable error))completionHandler;

  • WKWebView需要添加WebKit.framework陷猫,最低支持版本iOS8秫舌,Xib不能用,只能代碼寫界面。

  • 條件允許的情況下指攒,建議用WKWebView米罚,系統(tǒng)性能的提升是硬道理。

JS調(diào)Native

  • UIWebView - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;

  • WKWebView - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler;

  • NSURLRequest中有NSURL參數(shù)嘱支,以格式scheme://host?query約定好,JS告訴Native想要達(dá)到的目的,Native根據(jù)參數(shù)完成相應(yīng)的功能零抬。

  • JS和iOS、Android的寫法需要相互配合宽涌,才能完成相應(yīng)的通訊過程平夜。

JS調(diào)用Native大致步驟

  • Step1:Native通過截取的url,將scheme://host?key1=value1&key2=value2格式解析出來卸亮。一般根據(jù)scheme判斷是否目標(biāo)JS忽妒,決定是否處理;host部分可以約定為模塊名或者類名或者函數(shù)名等兼贸;問號后面的key1=value1&key2=value2就是url的query部分段直,可以放參數(shù)名;當(dāng)然也可以host部分不用溶诞,將所有信息都放入后面的參數(shù)中鸯檬。

  • Step2: Native執(zhí)行一段事先定義的固定的JS代碼,告訴JS已經(jīng)正確收到命令螺垢。比如:

[self.webView evaluateJavaScript:@"bridge.nativeCallComplete()" completionHandler:nil];
  • Step3:JS端收到命令響應(yīng)之后等待或者做其他事情喧务,Native端根據(jù)解析出來的參數(shù)調(diào)用本地模塊完成響應(yīng)的功能

  • Step4:Native執(zhí)行完畢后,執(zhí)行一段事先定義的固定的JS代碼枉圃,告訴JS執(zhí)行結(jié)果功茴。
    比如:

[self.webView evaluateJavaScript:@"[self.webView evaluateJavaScript:@"javascript:bridge.invokeJs('result=3')" completionHandler:nil];" completionHandler:nil];
  • Step5:JS端根據(jù)收到的結(jié)果,決定下一步的響應(yīng)讯蒲。

參考文章

UIWebView與JavaScript(JS) 回調(diào)交互

WebViewJavascriptBridge簡介

通過前面的介紹可以知道痊土,Native調(diào)用JS和JS調(diào)用Native是很不一樣的。并且在JS調(diào)用Native的過程中墨林,有好幾次用到Native調(diào)用JS的過程(告訴JS命令接收赁酝,告訴JS處理結(jié)果)。估計(jì)這也是讓人感覺復(fù)雜的地方旭等。
WebViewJavascriptBridge的設(shè)計(jì)比較巧妙酌呆,經(jīng)過包裝,JS和Native互相調(diào)用的寫法完全一致搔耕,實(shí)現(xiàn)了“全雙工通訊”隙袁。
marcuswestin/WebViewJavascriptBridge

通訊函數(shù)

typedef void (^WVJBResponseCallback)(id responseData);
typedef void (^WVJBHandler)(id data, WVJBResponseCallback responseCallback);
- (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler;
- (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback;

在一端用registerHandler進(jìn)行注冊痰娱,在另一端就可以用callHandler進(jìn)行調(diào)用,調(diào)用結(jié)果通過Block以異步的方式告知菩收。從調(diào)用形式上看梨睁,Native和JS完全一樣,使用起來非常方便娜饵。

Native端注意點(diǎn)

+ (instancetype)bridgeForWebView:(WKWebView*)webView;
- (void)setWebViewDelegate:(id<WKNavigationDelegate>)webViewDelegate;
  • 第一個函數(shù)將Bridge和某個webView建立聯(lián)系

  • 第二個函數(shù)設(shè)置webView的代理(外部代理)坡贺,在函數(shù)內(nèi)部,Bridge是真正的代理箱舞,進(jìn)行截取url操作之后遍坟,Bridge會調(diào)用在這里設(shè)的這個代理,讓外部代理起作用晴股。代理模式中WebView的代理只有一個愿伴,就是Bridge,通過“二傳手”模式电湘,從外面看起來好像WebView有兩個代理一樣隔节。

  • 如果是UIWebView,使用的類是WebViewJavascriptBridge

  • 如果是WKWebView胡桨,使用的類是WKWebViewJavascriptBridge

  • 兩者的接口函數(shù)幾乎是一樣的官帘,以上兩個類基本上也是“二傳手”,只是一個容器昧谊,真正的工作在類WebViewJavascriptBridgeBase中完成刽虹。

  • Android的代碼也是有的,不過是另外的第三方庫呢诬,是為了配合這個庫而寫的Android版本涌哲。這樣JS、iOS尚镰、Android可以良好地配合起來阀圾。
    jesse01/WebViewJavascriptBridge

JS端注意點(diǎn)

  • JS端有固定的寫法,里面有一個例子狗唉,“ExampleApp.html”這里面有現(xiàn)成的代碼初烘,自己只要往里面填自定義的函數(shù)就可以。
    function setupWebViewJavascriptBridge(callback) {
        if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
        if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
        window.WVJBCallbacks = [callback];
        var WVJBIframe = document.createElement('iframe');
        WVJBIframe.style.display = 'none';
        WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__';
        document.documentElement.appendChild(WVJBIframe);
        setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
    }

    setupWebViewJavascriptBridge(function(bridge) {
        var uniqueId = 1
        function log(message, data) {
            var log = document.getElementById('log')
            var el = document.createElement('div')
            el.className = 'logLine'
            el.innerHTML = uniqueId++ + '. ' + message + ':<br/>' + JSON.stringify(data)
            if (log.children.length) { log.insertBefore(el, log.children[0]) }
            else { log.appendChild(el) }
        }

        bridge.registerHandler('testJavascriptHandler', function(data, responseCallback) {
            log('ObjC called testJavascriptHandler with', data)
            var responseData = { 'Javascript Says':'Right back atcha!' }
            log('JS responding with', responseData)
            responseCallback(responseData)
        })

        document.body.appendChild(document.createElement('br'))

        var callbackButton = document.getElementById('buttons').appendChild(document.createElement('button'))
        callbackButton.innerHTML = 'Fire testObjcCallback'
        callbackButton.onclick = function(e) {
            e.preventDefault()
            log('JS calling handler "testObjcCallback"')
            bridge.callHandler('testObjcCallback', {'foo': 'bar'}, function(response) {
                log('JS got response', response)
            })
        }
    })

(二)通過JavaScriptCore.framework

  • 需要引入系統(tǒng)庫JavaScriptCore.framework

  • 最低支持iOS7

  • 有見到過用的場所分俯,但是不多

  • 對于iOS和Android兩個平臺肾筐,JS端是否能夠統(tǒng)一,存在不確定性

關(guān)于iOS7里的JavaScriptCore framework
JavaScriptCore框架

(三)通過WKWebView的WKUserContentController

  • 最低支持iOS8

  • 需要引入庫WebKit.framework

  • 這是采用注入缸剪,代理監(jiān)聽吗铐,發(fā)消息等方式實(shí)現(xiàn)的

  • JS端無法統(tǒng)一iOS和Android兩個平臺的處理

WKWebView與Js實(shí)戰(zhàn)(OC版)

如何選擇

  • 采用WebViewJavascriptBridge目前來看應(yīng)該是首選,iOS杏节、Android唬渗、JS三個平臺配合都考慮到了典阵,通信方式也比較簡單

  • 最低支持iOS8,WKWebView的注入方式是值得考慮的镊逝。只是目前還沒有好的第三方庫支持壮啊。JS需要對iOS和Android需要分別處理,因?yàn)閮烧叩淖⑷敕绞讲煌0搿2贿^這個方向是值得嘗試的他巨,功能強(qiáng)大。

  • 不采用WebViewJavascriptBridge减江,利用截取url的方式是目前大多數(shù)的方案,也是值得考慮的捻爷。JS辈灼、Android、iOS三者要彼此協(xié)調(diào)好也榄。

  • JavaScriptCore在iOS8之前由于注入的方式還是有吸引力的巡莹。不過WKWebView也提供了注入的方式,目前還看不出有什么優(yōu)勢甜紫。當(dāng)前降宅,也是使用者比較少的一種方式。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末囚霸,一起剝皮案震驚了整個濱河市腰根,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拓型,老刑警劉巖额嘿,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異劣挫,居然都是意外死亡册养,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門压固,熙熙樓的掌柜王于貴愁眉苦臉地迎上來球拦,“玉大人,你說我怎么就攤上這事帐我】擦叮” “怎么了?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵焚刚,是天一觀的道長点弯。 經(jīng)常有香客問我,道長矿咕,這世上最難降的妖魔是什么抢肛? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任狼钮,我火速辦了婚禮,結(jié)果婚禮上捡絮,老公的妹妹穿的比我還像新娘熬芜。我一直安慰自己,他們只是感情好福稳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布涎拉。 她就那樣靜靜地躺著,像睡著了一般的圆。 火紅的嫁衣襯著肌膚如雪鼓拧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天越妈,我揣著相機(jī)與錄音季俩,去河邊找鬼。 笑死梅掠,一個胖子當(dāng)著我的面吹牛酌住,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播阎抒,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼酪我,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了且叁?” 一聲冷哼從身側(cè)響起都哭,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谴古,沒想到半個月后质涛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡掰担,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年汇陆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片带饱。...
    茶點(diǎn)故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡毡代,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出勺疼,到底是詐尸還是另有隱情教寂,我是刑警寧澤,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布执庐,位于F島的核電站酪耕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏轨淌。R本人自食惡果不足惜迂烁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一看尼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧盟步,春花似錦藏斩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至黄橘,卻和暖如春兆览,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背塞关。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工拓颓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人描孟。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像砰左,于是被迫代替她去往敵國和親匿醒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,133評論 25 707
  • 前言:iOS 開發(fā)中缠导,h5 和原生實(shí)現(xiàn)通信有多種方式廉羔, JSBridge 就是最常用的一種,各 JSBridge ...
    ShannonChenCHN閱讀 8,481評論 11 63
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫僻造、插件憋他、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,103評論 4 62
  • 今天在宿舍聽歌,音樂可真不是個好東西髓削。 想起來那年找各種借口跑到大連只為在誰的學(xué)校門口籃球場邊上過一過竹挡,走的時候就...
    崔鷺濤閱讀 226評論 0 0
  • 廢棄玻璃瓶經(jīng)過本菇?jīng)龅氖掷L改造,瞬間成了花瓶立膛,種了一株小肉肉[害羞][害羞]心安寧揪罕,就是好生活[玫瑰][太陽][太陽]
    基礎(chǔ)繪畫社閱讀 852評論 0 8