前言
目前,很多APP里面都會有HTML5網頁,我們除了簡單的用WebView加載顯示外,很多情況下,我們需要OC端與WebView進行交互,比如點擊WebView上面的按鈕調用OC端的函數實現具體操作。
這次主要是使用第三方的開源項目<mark>WebViewJavascriptBridge</mark>來幫助實現。
使用步驟
方法1
去GitHub下載<mark>WebViewJavascriptBridge</mark>
解壓縮包,將<mark>WebViewJavascriptBridge</mark>文件拖入到工程中
在需要使用的類中引入頭文件<mark>"WebViewJavascriptBridge.h"
方法2
安裝cocoaPods后,直接在Podfile中輸入pod 'WebViewJavascriptBridge', '~> 5.0',將WebViewJavascriptBridge引入工程后,下面步驟參考方法1。
具體使用
- 創建并初始化<mark>WebViewJavascriptBridge</mark>的實例
#import "BaseWebViewController.h"
#import "WebViewJavascriptBridge.h"
@interface BaseWebViewController ()<UIWebViewDelegate>
{
UIWebView *_webView;
WebViewJavascriptBridge *_bridge;
}
@end
- 具體代碼實現
OC端
//第一步開啟日志
//開啟日志,方便調試
[WebViewJavascriptBridge enableLogging];
//第二步,建立橋梁
//給webView建立起js與OC的溝通橋梁
_bridge = [WebViewJavascriptBridge bridgeForWebView:_webView];
//設置代理,如果不需要可以不設置
[_bridge setWebViewDelegate:self];
//第三步,注冊HandleName,用于給JS端調用iOS端
// JS主動調用OjbC的方法
// 這是JS會調用getUserIdFromObjC方法,這是OC注冊給JS調用的
// JS需要回調,當然JS也可以傳參數過來。data就是JS所傳的參數,不一定需要傳
// OC端通過responseCallback回調JS端,JS就可以得到所需要的數據
[_bridge registerHandler:@"getUserIdFromObjC"handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@"js call getUserIdFromObjC, data from js is %@", data);
if (responseCallback) {
// 反饋給JS
responseCallback(@{@"userId": @"123456"});
}
}];
/*js按鈕點擊后,OC收到即可執行需要的操作*/
[_bridge registerHandler:@"getBlogNameFromObjC"handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@"js call getBlogNameFromObjC, data from js is %@", data);
if (responseCallback) {
// 反饋給JS
responseCallback(@{@"from": @"Yapi"});
//點擊js界面按鈕控制OC界面跳轉
PlayViewController *playVC = [[PlayViewController alloc] init];
[self.navigationController pushViewController:playVC animated:YES];
}
}];
[_bridge callHandler:@"getUserInfos" data:@{@"name": @"jinBank"} responseCallback:^(id responseData) {
NSLog(@"from js: %@", responseData);
}];
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方法都要放在此處注冊,才能調用通過JS調用OC或者讓OC調用這里的JS*/
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)
}
}
/* Initialize your app here */
/*我們在這注冊一個js調用OC的方法,不帶參數,且不用ObjC端反饋結果給JS:打開本demo對應的blog*/
bridge.registerHandler('openWebviewBridgeArticle', function() {
log("openWebviewBridgeArticle was called with by ObjC(打開blog)")
})
/*JS給ObjC提供公開的API,在ObjC端可以手動調用JS的這個API。接收ObjC傳過來的參數,且可以回調ObjC*/
bridge.registerHandler('getUserInfos', function(data, responseCallback) {
log("Get user information from ObjC: ", data)
responseCallback({'userId': '123456', 'blog': '博客'})
})
/*JS給ObjC提供公開的API,ObjC端通過注冊,就可以在JS端調用此API時,得到回調。ObjC端可以在處理完成后,反饋給JS,這樣寫就是在載入頁面完成時就先調用*/
bridge.callHandler('getUserIdFromObjC', function(responseData) {
log("JS call ObjC's getUserIdFromObjC function, and js received response:", responseData)
})
document.getElementById('blogId').onclick = function (e) {
log('js call objc: getBlogNameFromObjC')
bridge.callHandler('getBlogNameFromObjC', {'blogURL': 'http://www.baidu.com'}, function(response) {
log('JS got response', response)
})
}
})
- JS調OC
- 什么是JS調OC
舉個例子,在網頁上有個登錄按鈕,點擊此登錄按鈕后,具體的登錄操作在OC端實現,即登錄功能需要OC端有個Login方法實現。
- 具體流程
實際開發中,實現上述功能,我們需要跟負責網頁開發的同事商定一個方法名稱,假設叫loginCallBack,我們在OC端就要注冊這個事件并負責具體實現。當用戶點擊網頁上的登錄按鈕時,它就會通知OC端的注冊者去執行這個方法,有點類似block執行順序。
-
具體代碼實現
1.OC端
/js按鈕點擊后,OC收到即可執行需要的操作/
[_bridge registerHandler:@"loginCallBack"handler:^(id data, WVJBResponseCallback responseCallback) {
if (responseCallback) {
// 反饋給JS
responseCallback(@{@"from": @"Yapi"});
//點擊js界面按鈕控制OC界面跳轉
PlayViewController *playVC = [[PlayViewController alloc] init];
[self.navigationController pushViewController:playVC animated:YES];
}
}];
```
2.JS端
```
//js端執行了callHandler后,oc端就會執行block中的內容
document.getElementById('blogId').onclick = function (e) {
bridge.callHandler('loginCallBack', function(response) {
log('JS got response', response)
})
}
```
-
OC調JS
- 什么是OC調JS
理解了JS調用OC,OC調JS就好理解了,例如,現在我們在OC端有個輸入框,輸入了用戶名后讓它顯示到網頁上的用戶名處,這樣OC端要實現的事件讓網頁去真正實現了,就是OC調JS。
- 具體流程
和JS調OC一樣,兩端需要商量一個相同的名字(getUserInfos),在JS端注冊這個事件并負責具體實現,OC端觸發事件后去網頁找具體事件的實現體并執行。
- 具體代碼實現
1.JS端
//js端注冊Handler后,如果oc端執行了OC端代碼,{}中的內容就會癟執行 bridge.registerHandler('getUserInfos', function(data, responseCallback) { log("Get user information from ObjC: ", data) responseCallback({'userId': '123456', 'blog': '博客'}) })
2.OC端
[_bridge callHandler:@"getUserInfos" data:@{@"name": @"京金所"} responseCallback:^(id responseData) { NSLog(@"from js: %@", responseData); }];
注意點
一定要注意和網頁端商定的方法名必須要保證OC代碼 里和網頁編碼里統一。在調用之前,必須要先注冊事件,寫好實現體。
總結
本篇文章只是簡單的介紹了 <mark>WebViewJavascriptBridge</mark>的一些基本用法,還有一些方法沒有詳講,希望大家在掌握了這幾個方法的使用后也去研究一下里面的其他方法。另外,本文重點是讓iOS工程師能快速使用,一些原理的東西還有JS方面的編碼都省略了,可能文中有些地方理解不當或者不夠深入,后期會再完善修改.最后,希望大家多提寶貴意見。