在平常的开发中,经常要用到H5与App混编,最根本的思路都是利用UIWebView(或者WKWebView)来加载H5,从而实现H5与OC的交互。H5与OC混编主要有如下几种方式:
一、UIWebView加载H5页面,H5点击事件处理通过window.location来导航一个自定义协议的URL;App通过UIWebViewDelegate方法- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType来截获Frame的加载。代码片段如下:
H5端: 点击事件中加入代码window.location='iosfeedback://?type=1000' 其中iosfeedback为自定义的协议,用来区分不同的事件,?后面用来传参数对,当然我们也可以用URL的fragment来传递数据
App端代码:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
NSString* scheme = request.URL.scheme;
NSString* query = request.URL.query;
NSDictionary* queryDic = [query dictionaryFromURLParameters];
if ([scheme isEqualToString:@"iosfeedback"])
{
NSString* type = [queryDic valueForKey:@"type"];
//下面加入逻辑处理
}
return YES;
}
OC通过stringByEvaluatingJavaScriptFromString来调用JS代码。
二、高级一点的用facebook的reactive native,这是一个重量级的开源库,暂时还没用过
三、本文的主角WebViewJavascriptBridge,具体使用方法请见github,笔者通过阅读WebViewJavascriptBridge源码来总结一下他的实现思路
1、如何实现OC调用JS?通过跟踪WebViewJavascriptBridge方法- (void)callHandler:(NSString *)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback发现调用堆栈为WebViewJavascriptBridge::callHandler->WebViewJavascriptBridgeBase::sendData->WebViewJavascriptBridgeBase::_dispatchMessage。WebViewJavascriptBridgeBase方法- (void)_dispatchMessage:(WVJBMessage*)message做了两件事:message序列化为JSON字符串messageJSON、执行JS方法WebViewJavascriptBridge._handleMessageFromObjC(messageJSON)。
2、JS如何调用OC?通过WebViewJavascriptBridge 方法- (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler注册JS调用,handler回调不仅可以收到JS传递的数据,也可以再传递数据给JS
3、上面1、2点中JS与OC互调,实际上都是NSString * WebViewJavascriptBridge_js()方法里面的JS代码实现了一套消息分发机制。
ExampleApp.html里面setupWebViewJavascriptBridge方法先创建一个wvjbscheme://__BRIDGE_LOADED__的iframe,WebViewJavascriptBridge方法- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType识别到这个iframe,然后执行WebViewJavascriptBridge_js()返回的JS代码注入,通过此步操作JS整套消息路由机制建立起来了。这段JS代码实际上是定义了一个JS自启动方法,并且定义了一个全局WebViewJavascriptBridge对象,doSend方法通过创建一个Src为wvjbscheme://__WVJB_QUEUE_MESSAGE__的ifframe并且把消息加入到一个sendMessageQueue队列中,webview识别到这个Url后直接调用WebViewJavascriptBridge._fetchQueue()取出这些消息,然后调用OC相应的回调方法。
说到底:OC与JS互调的原理就是stringByEvaluatingJavaScriptFromString与- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType