在開發(fā)中涉及到網(wǎng)頁與iOS原生交互,于是就想到了WebViewJavascriptBridge 這個開源庫。經(jīng)過最近幾天的研究和了解算是熟悉了它的使用和大致的處理過程偶妖。以此記錄作為自己學習總結(jié)習慣的開始肌访,也便于不熟悉它的人能快速使用它。
內(nèi)容包括三個部分盒使。
-
WebViewJavascriptBridge基本使用
-
OC中調(diào)用JS方法分析
-
JS中調(diào)用OC方法分析
<p>
1崩掘、WebViewJavascriptBridge基本使用:
導入工程包含文件如下(圖1):
其支持UIWebView 和 WKWebView,我用的是UIWebView少办,測試文件** test.html 苞慢。
** oc端的操作
首先添加頭文件#import <WebViewJavascriptBridge.h>
//初始化_webBridge對象
_webBridge =[WebViewJavascriptBridge bridgeForWebView:_webview];
[_webBridge setWebViewDelegate:self];
js和iOS方法相互調(diào)用之前需要先注冊,如js要調(diào)用oc中的方法 * objc_fun1 *英妓,在oc文件中操作如下
//注冊方法供js處調(diào)用
[_webBridge registerHandler:@"objc_fun1" handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@"rec data from js :%@",data);
responseCallback(@"i am from objc!");
}];
//objc_fun1:注冊方法的名稱供js端調(diào)用
//handler:具體的方法操作挽放,參數(shù)data — js調(diào)用時傳遞的參數(shù) ,responseCallback—js 回調(diào)操作蔓纠。
//調(diào)用js中的方法
[_webBridge callHandler:@"js_fun1" data:@{@"key":@"hello js"} responseCallback:^(id responseData) {
NSLog(@"from js :%@",responseData);
}];
js端的操作
相關操作基本固定辑畦,在 test.html 中,方法 function setupWebViewJavascriptBridge(callback){}的定義不需要改動腿倚,我們只是在方法的調(diào)用時纯出,在callback 中加入自己的操作。這里注冊oc 需要調(diào)用的方法,或者調(diào)用oc已注冊過的方法
setupWebViewJavascriptBridge(function(bridge) {
//register functin
bridge.registerHandler('js_fun1', function(data, responseCallback) {
console.log("JS Echo called with:", data)
responseCallback(data)
})
// add button
var btn = document.getElementById('divid1').appendChild(document.createElement('button'))
btn.innerHTML = "callOCFunction"
btn.style="background-color:red;text-align:center"
btn.onclick = function(e){
e.preventDefault()
bridge.callHandler('objc_fun1', {'key':'hello oc,I from JS'}, function responseCallback(responseData) {
var e =document.getElementById('result')
e.innerHTML = "oc response: " + responseData;
})
}
})
//html部分
<body>
<p>this is webviewJavascriptBridge demo</p>
<div>
<p id='result'></p>
</div>
<div style = "background-color:blue;text-align:center;" id = 'divid1' height:40px></div>
</body>
在此注冊了方法中js_fun1可供oc處調(diào)用暂筝,添加了測試按鈕callOCFunction箩言,點擊通過bridge.callHandler() 調(diào)用oc端的方法objc_fun1,返回的結(jié)果在頁面上顯示焕襟。運行程序后點擊按鈕達到了預期結(jié)果分扎,到這里算是完成了基本實用。
2胧洒、OC中調(diào)用JS方法分析:
WebViewJavascriptBridge中js與oc的交互主要通過- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
url攔截然后對url分析進行js代碼注入畏吓,最終實現(xiàn)js與oc的方法相互調(diào)用。<p>
首次加載test.html時發(fā)起一次請求操作卫漫,
url = 'wvjbscheme://__BRIDGE_LOADED__',攔截到該url菲饼,通過- >>(void)injectJavascriptFile 方法進行js注入, NSString *js = WebViewJavascriptBridge_js();此js代碼在#import "WebViewJavascriptBridge_JS.h"中列赎,對js中>WebViewJavascriptBridge對象方法和變量進行初始化 主要方法如下:
function registerHandler(handlerName, handler);//注冊方法
function callHandler(handlerName, data, responseCallback);//調(diào)用方法
function _doSend(message, responseCallback);
function _fetchQueue();
function _dispatchMessageFromObjC(messageJSON);
function _handleMessageFromObjC(messageJSON);
<p>
OC中調(diào)用JS方法順序
1.首先調(diào)用方法 - (void)callHandler:(NSString *)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback
參數(shù)data宏悦,參數(shù)形式js端書寫語法。
參數(shù)responseCallback包吝,最后的回調(diào)操作饼煞。
2.- (void)sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName
把發(fā)送的數(shù)據(jù)封裝在一個字典中,如果有responseCallback同時生成一個回調(diào)id(objc_cb_1形式的字符串)诗越。
3.- (void)_queueMessage:(WVJBMessage*)message
4.- (void)_dispatchMessage:(WVJBMessage*)message
把消息對象轉(zhuǎn)化為json字符串,添加字符格式化的處理-> messageJSON砖瞧,
獲取js代碼字符串
NSString* javascriptCommand = [NSString stringWithFormat:@"WebViewJavascriptBridge._handleMessageFromObjC('%@');", messageJSON];
執(zhí)行js代碼
[self _evaluateJavascript:javascriptCommand];
js中依次調(diào)用
function _handleMessageFromObjC(messageJSON) function _dispatchMessageFromObjC(messageJSON)執(zhí)行js中方法操作
方法結(jié)束后,如果此時的oc方法有回調(diào)操作->通過function _doSend(message, responseCallback)
再次發(fā)起url請求嚷狞。然后操作回到oc端块促。
<p>
oc中攔截url請求,分析請求類型為WVJB_QUEUE_MESSAGE調(diào)用方法5
5.- (void)flushMessageQueue:(NSString *)messageQueueString
根據(jù)js傳入的參數(shù)獲取 回調(diào)id 'responseId'取出oc方法的回調(diào)代碼塊執(zhí)行床未,然后在self.responseCallbacks移除已執(zhí)行的操作竭翠。
NSString* responseId = message[@"responseId"];
if (responseId) {
WVJBResponseCallback responseCallback = _responseCallbacks[responseId];
responseCallback(message[@"responseData"]);
[self.responseCallbacks removeObjectForKey:responseId];
}
至此,oc調(diào)用js方法執(zhí)行結(jié)束薇搁。
3斋扰、JS中調(diào)用OC方法分析:
依次調(diào)用方法順序
JS中的方法操作
在文件#import "WebViewJavascriptBridge_JS.h"中定義的方法
1.function callHandler(handlerName, data, responseCallback);
2.function _doSend(message, responseCallback) 在這個方法中生成回調(diào)的id,并保存js端的回調(diào)操作,然后發(fā)起一次請求回到OC端操作啃洋。
oc中攔截url請求传货,分析請求類型為WVJB_QUEUE_MESSAGE調(diào)用方法3
3.- (void)flushMessageQueue:(NSString *)messageQueueString
主要操作代碼如下:
{
WVJBResponseCallback responseCallback = NULL;
NSString* callbackId = message[@"callbackId"];
if (callbackId) {
responseCallback = ^(id responseData) {
if (responseData == nil) {
responseData = [NSNull null];
}
WVJBMessage* msg = @{ @"responseId":callbackId, @"responseData":responseData };
[self _queueMessage:msg];
};
} else {
responseCallback = ^(id ignoreResponseData) {
// Do nothing
};
}
WVJBHandler handler = self.messageHandlers[message[@"handlerName"]];
if (!handler) {
NSLog(@"WVJBNoHandlerException, No handler for message from JS: %@", message);
continue;
}
handler(message[@"data"], responseCallback);
}
根據(jù)傳遞過來的方法名,參數(shù)裂允,和回調(diào)調(diào)用oc方法handler(message[@"data"], responseCallback);
如果有回調(diào)responseCallback损离,oc方法執(zhí)行完后調(diào)用[self _queueMessage:msg];
然后操作同OC中調(diào)用JS方法順序中步驟3哥艇、4又回到JS端執(zhí)行
function _dispatchMessageFromObjC(messageJSON) {
setTimeout(function _timeoutDispatchMessageFromObjC() {
var message = JSON.parse(messageJSON);
var messageHandler;
var responseCallback;
if (message.responseId) {
responseCallback = responseCallbacks[message.responseId];
if (!responseCallback) {
return;
}
responseCallback(message.responseData);
delete responseCallbacks[message.responseId];
}
根據(jù)message.responseId 找到原來保存的回調(diào)操作绝编、執(zhí)行完畢后,刪除該id的操作,至此JS中調(diào)用OC方法的操作流程結(jié)束十饥。
總結(jié):通過WebViewJavascriptBridge來實現(xiàn)JS窟勃、OC的交互,主要通過在OC端進行請求攔截逗堵,根據(jù)url的類型判斷不同的操作秉氧,然后在通過js注入和執(zhí)行來完成方法的調(diào)用,所以每次的事件可能會在OC和JS間多次來回切換蜒秤。
以上為使用WebViewJavascriptBridge的操作和分析汁咏,若理解有不對的地方謝謝指出。