使用WebViewJavascriptBridge實(shí)現(xiàn)WebView和JavaScript交互。
項(xiàng)目開發(fā)過程中,可能會(huì)遇到WebView和H5交互的情況。我們可以用WebViewJavascriptBridge第三方庫來實(shí)現(xiàn)。
主要有兩個(gè)方法:
- (void)callHandler:(NSString*)handlerName data:(id)data;
這個(gè)方法是發(fā)送消息的方法,當(dāng)OC或者JS需要發(fā)消息給對(duì)方時(shí)苹威,調(diào)用這個(gè)方法,handlerName是發(fā)送消息的名字驾凶,data是需要發(fā)送的數(shù)據(jù)牙甫,對(duì)方需要先用下面這個(gè)方法來注冊,才能接收消息
- (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler;
這個(gè)方法可以理解為是接收消息的方法调违,需要先注冊窟哺,handlerName是消息名,和對(duì)方發(fā)消息的方法名要一樣技肩,handler是個(gè)block且轨,用來接收傳來的消息
這次實(shí)現(xiàn)一個(gè)簡單的功能,點(diǎn)擊H5上面的登錄按鈕虚婿,跳轉(zhuǎn)到原生的登錄頁面旋奢,用戶登錄后,把用戶名和密碼傳給H5然痊。H5里JS代碼使用WebViewJavascriptBridgedemo里的JS代碼
首先至朗,我們在頁面放放置一個(gè)UIWebView,并加載本地的HTML文件
NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil];
NSURL *baseURL = [NSURL fileURLWithPath:htmlPath];
[_webView loadHTMLString:appHtml baseURL:baseURL];
頁面很簡單剧浸,一個(gè)登錄按鈕
我們在JS里面寫按鈕點(diǎn)擊調(diào)用的方法:
var callbackButton = document.getElementById('buttons').appendChild(document.createElement('button'))
callbackButton.innerHTML = '立即登錄'
callbackButton.onclick = function(e) {
e.preventDefault()
log('JS調(diào)用"testObjcCallback"發(fā)消息給OC')
bridge.callHandler('needLogin', {'login': '1'}, function(response) {
log('JS收到OC的回復(fù):', response)
})
}
當(dāng)按鈕點(diǎn)擊時(shí)锹引,JS會(huì)發(fā)給OC一個(gè)名為“needLogin”的消息,數(shù)據(jù)為“{"login":"1"}”
當(dāng)然唆香,為了OC能收到消息嫌变,需要在頁面加載完HTML后,注冊一下
- (void)viewDidLoad {
[super viewDidLoad];
//加載HTML
NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil];
NSURL *baseURL = [NSURL fileURLWithPath:htmlPath];
[_webView loadHTMLString:appHtml baseURL:baseURL];
//打開調(diào)試開關(guān)
[WebViewJavascriptBridge enableLogging];
//建立WebView和H5的連接
_bridge = [WebViewJavascriptBridge bridgeForWebView:_webView];
//設(shè)置代理
[_bridge setWebViewDelegate:self];
//注冊以接收數(shù)據(jù)
[_bridge registerHandler:@"needLogin" handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@"JS發(fā)來的消息:%@",data);
if ([data[@"login"] integerValue] == 1) {
LoginViewController *a = [[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"a"];
a.delegate = self;
[self.navigationController pushViewController:a animated:YES];
}
responseCallback([NSString stringWithFormat:@"收到JS的消息%@",data]);
}];
}
我們注冊了一個(gè)名字也為“needLogin”的handle來接收J(rèn)S發(fā)來的消息躬它,并在收到消息后腾啥,返回給JS一個(gè)回復(fù),告訴JS我們已經(jīng)收到它發(fā)送的消息冯吓,在判斷消息里login=1的時(shí)候倘待,我們將會(huì)跳轉(zhuǎn)到登錄頁面,接下來我們點(diǎn)擊按鈕,將會(huì)跳轉(zhuǎn)到登錄頁面
在調(diào)試窗口我們可以看到JS發(fā)來的消息
我們在登錄頁面按鈕方法里寫代碼桑谍,把用戶填寫的信息傳給上個(gè)頁面
- (IBAction)login:(id)sender {
if ([_delegate respondsToSelector:@selector(loginSuccess:password:)]) {
[_delegate loginSuccess:_userNameTextField.text password:_passwordTextField.text];
}
[self.navigationController popViewControllerAnimated:YES];
}
在WebView頁面延柠,接收登錄頁面?zhèn)鱽淼挠脩裘兔艽a,并在這里把用戶名和密碼發(fā)給JS
- (void)loginSuccess:(NSString *)userName password:(NSString *)password{
[_bridge callHandler:@"loginSuccess" data:@{@"username":userName,@"password":password} responseCallback:^(id responseData) {
NSLog(@"%@",responseData);
}];
}
同樣的锣披,JS也需要注冊一個(gè)名字為“l(fā)oginSuccess”的handle來接收信息,并且我們在收到消息時(shí),告訴OC我們已成功收到
bridge.registerHandler('testJavascriptHandler', function(data, responseCallback) {
log('JS收到OC的消息', data)
var responseData = { 'JS':'receive username and password' }
log('JS回復(fù)OC', responseData)
responseCallback(responseData)
})
我們輸入用戶名為66666雹仿,密碼為88888并點(diǎn)擊登錄
調(diào)試已經(jīng)有輸出增热,JS已經(jīng)收到我們的信息了
WebViewJavascriptBridge的JS也會(huì)在H5頁面上打印各個(gè)步驟的輸出:
至此,這個(gè)簡單的交互成功完成
GitHub:WebViewVsJS