WebViewJavascriptBridge学习

参考:
WebViewJavascriptBridge源码分析
WebViewJavascriptBridge 原理分析

源码地址:https://github.com/marcuswestin/WebViewJavascriptBridge

上面两个原理已经讲的很清楚了,重点讲了JS如何调用Native的代码,即使用了URL拦截的方法,就不再详细分析源码了。大概流程如图:
这里写图片描述
1 Native端通过registerHandler注册方法,即保存到messageHandlers的Dictionary里

- (void)registerHandler:(NSString *)handlerName handler:(WVJBHandler)handler {
    _base.messageHandlers[handlerName] = [handler copy];
}

2 js端调用callHandler方法,通过iframe发送网络请求,Native端通过UIViewDelegate的方法拦截,如果和WebViewJavascriptBridge的scheme相同则执行flushMessageQueue,参数相关的信息是通过调用js中的_fetchQueue取到的
3 在flushMessageQueue会判断responseId和callbackId,responseId标识的是Native调用js的方法后,js端执行Native的回调;callbackId表示的是js直接调用Native的代码

在以前的版本中,是WebView的Delegate方法中通过判断numRequestsLoading计数来注入injectJavascriptFile的代码,但是计数可能会存在问题,导致没有调用Bridge相关的代码

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    if (webView != _webView) { return; }

    _numRequestsLoading--;

    if (_numRequestsLoading == 0 && ![[webView stringByEvaluatingJavaScriptFromString:[_base webViewJavascriptCheckCommand]] isEqualToString:@"true"]) {
        [_base injectJavascriptFile:YES];
    }
    [_base dispatchStartUpMessageQueue];


    __strong WVJB_WEBVIEW_DELEGATE_TYPE* strongDelegate = _webViewDelegate;
    if (strongDelegate && [strongDelegate respondsToSelector:@selector(webViewDidFinishLoad:)]) {
        [strongDelegate webViewDidFinishLoad:webView];
    }
}

新版本里增加了新的scheme,不需要Native通过计数的方案来实现了,所以需要在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)
}

同时在UIViewViewDelegate的

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType

方法中增加了

if ([_base isBridgeLoadedURL:url]) {
    [_base injectJavascriptFile];
} 

这些都是通过URL拦截来实现的,但是苹果从iOS7开始引入了JavaScriptCore库,比如JSPatch就是这样实现的,后面再介绍吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值