一、综述
现在很多的应用都会在多种平台上发布,所以很多程序猿们都开始使用Hybrid App的设计模式。就是在app上嵌入网页,只要写一份网页代码,就可以跑在不同的系统上。在iOS中,app多是通过WebView来加载网页,由于功能需求等原因,代码中少不得要和跟网页交互。
二、原理
在iOS中,本地调用java script语言,是通过UIWebView中的实例方法stringByeva luatingjava scriptFromString:来实现的,该方法通过字符串对象的形式传入JS代码。
[webView stringByeva luatingjava scriptFromString:@"Math.random();"];
而JS调用本地的代码,则并没有现成的API,而是需要间接地通过一些方法来实现。我们利用UIWebView的代理方法,当UIWebView发起的所有网络请求,都可以通过delegate函数在Native层得到通知。这样,我们就可以在UIWebView内发起一个自定义的网络请求,比如:'wvjbscheme://__BRIDGE_LOADED__'。于是在UIWebView的delegate函数中,我们拦截url,只要发现是我们自定义的url,就不进行内容的加载,转而执行相应的调用逻辑。
三、WebViewjava scriptBridge的使用
1、WebViewjava scriptBridge简介
WebViewjava scriptBridge支持到iOS6之前的版本的,用于支持native的iOS与java script交互,接下来讲讲WebViewjava scriptBridge的基本原理及应该如何去使用,包括iOS端的使用和JS端的使用。
首先,看看WebViewjava scriptBridge.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 injectjava scriptFile];
} else if ([_base isQueueMessageURL:url]) {
NSString *messageQueueString = [self _eva luatejava script:[_base webViewjava scriptFetchQueyCommand]];
[_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];
}
}
WebViewjava scriptBridge是通过webview的代理拦截scheme,然后注入相应的JS,在拦截后,通过先通过-isBridgeLoadedURL:方法判断URL是否是需要bridge的URL,若是,则通过injectjava scriptFile方法注入JS;否则判断URL是否是队列消息,若是,则执行查询命令JS并刷新消息队列;如果都不匹配,URL被识别为未知的消息。
2、WebViewjava scriptBridge的使用
首先,要在JS中接入这个框架,这段代码是不变的
/**
* 此为js接入框架的函数
*/
function setupWebViewjava scriptBridge(callback) {
if (window.WebViewjava scriptBridge) { return callback(WebViewjava scriptBridge); }
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方法也需要在此处调用
*/
setupWebViewjava scriptBridge(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.inser