UIWebView中JS與OC互動 WebViewJavascriptBridge的使用,wkwebviewjs互動oc

來源:互聯網
上載者:User

UIWebView中JS與OC互動 WebViewJavascriptBridge的使用,wkwebviewjs互動oc
一、綜述

  現在很多的應用都會在多種平台上發布,所以很多程式猿們都開始使用Hybrid App的設計模式。就是在app上嵌入網頁,只要寫一份網頁代碼,就可以跑在不同的系統上。在iOS中,app多是通過WebView來載入網頁,由於功能需求等原因,代碼中少不得要和跟網頁互動。

二、原理

  在iOS中,本地調用Javascript語言,是通過UIWebView中的執行個體方法stringByEvaluatingJavaScriptFromString:來實現的,該方法通過字串對象的形式傳入JS代碼。

[webView stringByEvaluatingJavaScriptFromString:@"Math.random();"];

   而JS調用本地的代碼,則並沒有現成的API,而是需要間接地通過一些方法來實現。我們利用UIWebView的代理方法,當UIWebView發起的所有網路請求,都可以通過delegate函數在Native層得到通知。這樣,我們就可以在UIWebView內發起一個自訂的網路請求,比如:'wvjbscheme://__BRIDGE_LOADED__'。於是在UIWebView的delegate函數中,我們攔截url,只要發現是我們自訂的url,就不進行內容的載入,轉而執行相應的調用邏輯。

三、WebViewJavascriptBridge的使用

1、WebViewJavascriptBridge簡介

  WebViewJavascriptBridge支援到iOS6之前的版本的,用於支援native的iOS與javascript互動,接下來講講WebViewJavascriptBridge的基本原理及應該如何去使用,包括iOS端的使用和JS端的使用。

  首先,看看WebViewJavascriptBridge.m中Webview代理攔截的代碼:

- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener{    if (webView != _webView) { return; }        NSURL *url = [request URL];    if ([_base isCorrectProcotocolScheme:url]) {        if ([_base isBridgeLoadedURL:url]) {            [_base injectJavascriptFile];        } else if ([_base isQueueMessageURL:url]) {            NSString *messageQueueString = [self _evaluateJavascript:[_base webViewJavascriptFetchQueyCommand]];            [_base flushMessageQueue:messageQueueString];        } else {            [_base logUnkownMessage:url];        }        [listener ignore];    } else if (_webViewDelegate && [_webViewDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:request:frame:decisionListener:)]) {        [_webViewDelegate webView:webView decidePolicyForNavigationAction:actionInformation request:request frame:frame decisionListener:listener];    } else {        [listener use];    }}

   WebViewJavascriptBridge是通過webview的代理攔截scheme,然後注入相應的JS,在攔截後,通過先通過-isBridgeLoadedURL:方法判斷URL是否是需要bridge的URL,若是,則通過injectJavascriptFile方法注入JS;否則判斷URL是否是隊列訊息,若是,則執行查詢命令JS並重新整理訊息佇列;如果都不匹配,URL被識別為未知的訊息。

 

2、WebViewJavascriptBridge的使用

  首先,要在JS中接入這個架構,這段代碼是不變的

    /**     *  此為js接入架構的函數     */    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)    }

 

  然後OC要調用到的JS函數要在下面函數中使用bridge.registerHandler來註冊,而且JS需要調用的OC方法也要在下面的函數中用bridge.callHandler調用

/** *  OC調用的JS函數需在此處註冊,調用OC方法也需要在此處調用 */    setupWebViewJavascriptBridge(function(bridge) {var uniqueId = 1function 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) }}                                         //註冊一個給OC調用的函數,不帶參數        bridge.registerHandler('WebViewDidLoad',function() {            log("WebViewDidLoad")        })                //註冊一一個給OC調用的函數,接受OC傳來的一個參數和一個回調處理bridge.registerHandler('OC_Call_JS', function(data, responseCallback) {log('oc調用js -', data)var responseData = { 'Javascript response':'oc調用JS成功!' }log('js被調用後響應-', responseData)responseCallback(responseData)})document.body.appendChild(document.createElement('br'))var callbackButton = document.getElementById('buttons').appendChild(document.createElement('button'))callbackButton.innerHTML = 'JS_Call_ObjC'callbackButton.onclick = function(e) {e.preventDefault()log('JS call OC')            //此處調用OC方法bridge.callHandler('JS_Call_ObjC', {'foo': 'bar'}, function(response) {log('JS call OC sucess and get OC rsp', response)})}})

  需要注意的是:在setupWebViewJavascriptBridge(function(bridge) {}函數體內的代碼不能有錯誤,不然會導致不任何回調,不列印日誌(JS的是指令碼語言,跑到錯的地方就不跑了)。

 

  OC部分,首先開啟架構的日誌系統,然後關聯webView

[WebViewJavascriptBridge enableLogging];        _bridge = [WebViewJavascriptBridge bridgeForWebView:webView];

   JS需要調用的OC方法,要在OC代碼中註冊

[_bridge registerHandler:@"JS_Call_ObjC" handler:^(id data, WVJBResponseCallback responseCallback) {        NSLog(@"JS調用OC: %@", data);        responseCallback(@"OC被調用後響應:調用成功!");    }];

   而想要調用JS中註冊過的函數,在需要的地方用執行個體方法callHandler調用就可以了

    id data = @{ @"OC調用JS": @"Hi there, JS!" };    [_bridge callHandler:@"OC_Call_JS" data:data responseCallback:^(id response) {        NSLog(@"testJavascriptHandler responded: %@", response);    }];

 

四、小結

  最近因為項目需要,正在邊學邊做Hybrid App,剛好用到這個第三方,就寫了篇文分享出來,希望能幫到剛剛入手的人,以上執行個體的demo地址https://github.com/GarenChen/WebViewJSBridgeDemo喜歡的順手給個star ^_^;

推薦一些閱讀:

JSBridge——Web與Native互動之iOS篇:http://www.jianshu.com/p/9fd80b785de1

Hybrid App 開發模式:http://www.tuicool.com/articles/riE3Yn

WebViewJavascriptBridge:https://github.com/marcuswestin/WebViewJavascriptBridge

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.