内容字号:默认大号超大号

段落设置:段首缩进取消段首缩进

字体设置:切换到微软雅黑切换到宋体

JSBridge的思考:成长中的XDMicroJSBridge

2018-06-08 17:24 出处:清屏网 人气: 评论(0

前言

最近在做一个web与原生交互的需求,需求背景是这样子的,提供一个SDK里面包含一个webview用于加载业务h5,原生这边赋予webview选择相片、相机、刷脸、关闭原生界面的能力。虽然这个功能逻辑都是“熟悉的配方”,但还是有不少坑。

webview执行JS阻塞

项目一开始使用的桥接框架是以前项目用的桥接框架,但这个项目里面有一功能点跟旧项目不一样,旧项目只涉及到单图片的选择和上传而新项目需要支持多图片选择和上传,因为以前单图片选择上传整个过程响应较快,所以没关注执行JS时卡住了主线程,但这次项目是多图片选择上传而且h5多了ocr识别,导致整个处理相对耗时,原生这边执行JS一个回调将多张图片数据回传给h5处理,实例代码如下

[UIWebView stringByEvaluatingJavaScriptFromString:jsstring]

这个方法是一个同步方法,他会阻塞到JS方法执行结束才会返回,这时整个UI就会卡住。一开始的解决方案是通过原生这边异步派发队列解决同步的问题,但这又是一个坑,会致webview出现偶现的crash,这个稍后再详讲。原生这边不通,那就从JavaScript这一边着手,熟悉JavaScript的同学都知道,setTimeout方法能够实现异步,如果代码中设定了一个 setTimeout,那么浏览器便会在合适的时间,将代码插入任务队列,如果这个时间设为 0,就代表立即插入队列,但不是立即执行,仍然要等待前面代码执行完毕,所以 setTimeout 并不能保证执行的时间,是否及时执行取决于 JavaScript 线程是拥挤还是空闲,但它能够解决我们执行JS代码导致的同步问题,在我们原生调用JS回调之前用setTimeout做一层包装,相当于调用setTimeout方法,一调用就即刻返回,不阻塞线程,实例代码如下:

function asyncallback(callback,params) {if(typeof callback == 'function'){setTimeout(function () {callback(params);},0);}}

Why no WebViewJavascriptBridge

当给出第一版SDK给h5同事联调的时候,h5同事反馈了几个意见:

1、桥接依赖于协议定制和iframe,数据传输透明,存在安全隐患;

2、调用方式过于硬编码,调用时需要匹对填入方法名和参数,希望我这边设计出类似微信web api;

3、webview出现偶现的crash;

4、希望支持命名空间;

有人会问为什么不用业界更加成熟桥接框架WebViewJavascriptBridge,我们通过读源码可知WebViewJavascriptBridge底层还是依赖于协议定制和iframe,并不支持命名空间,而且crash还是会出现(网友反馈)。

综合上次的意见,我们需要重新设计我们的桥接框架,原框架的两端交互依赖iframe发请求、拦截请求来进行交互,iOS还有另外一个方案来实现两端交互:JavaScriptCore,想深入了解JavaScriptCore可以看 这篇文章 ,而且通过JavaScriptCore设计的js api的代码风格可以做到微信web api的效果。JavaScriptCore框架是一个苹果在iOS7引入的框架,该框架让 Objective-C 和 JavaScript 代码直接的交互变得更加的简单方便,而JavaScriptCore是苹果Safari浏览器的JavaScript引擎。通过JavaScriptCore,我们可以以写原生代码的方式写JavaScript,最终JavaScriptCore都会将我们的原生代码顺滑、安全转化为JavaScript层的实现。我们以这个JavaScriptCore框架为基础设计我们的桥接组件XDMicroJSBridge。

XDMicroJSBridge简概

关键类

JSContext: JSContext是JavaScript的执行环境;

JSValue: JSValue代表一个JavaScript实体,一个JSValue可以表示很多JavaScript原始类型例如boolean、 integers、doubles甚至包括对象和函数;

实现原理

先在原生注册对应的暴露给h5使用js API函数名,通过 [JSContext currentArguments] 捕获方法的参数,参数的类型是JSValue,JSValue提供一系列方法将值转换成合适的Objective-C值或对象,方便这边原生处理,通过block包装原生调用方法(相机、相册等),将block注入JSContext当中,命名空间的实现是往JSContext注入一个空实现的类,需要赋予命名空间的方法则将对应包装的block注入到这个空实现的类中。想了解具体实现点击 https://github.com/caixindong/XDMicroJSBridge 。实例代码如下:

- (void)registerAction:(NSString *)action handler:(XDMCJSBHandle)handler {
    if (action && handler) {
        __weak typeof(self) weakSelf = self;
        _context[_nameSpace][action] = ^{
            NSLog(@"action is %@",action);
            __strong typeof(weakSelf) strongSelf = weakSelf;
            strongSelf.webThread = [NSThread currentThread];
            NSLog(@"webThread is %@",[NSThread currentThread]);
            NSArray *args = [JSContext currentArguments];
            JSValue *last = (JSValue *)[args lastObject];
            XDMCJSBCallback ncallback = nil;
            NSMutableArray *trueArgs = [NSMutableArray arrayWithArray:args];
            if ([last isObject] && [[last toDictionary] isEqualToDictionary:@{}]) {
                [trueArgs removeLastObject];
                ncallback = ^(NSDictionary *params){
                    [strongSelf performSelector:@selector(_callJSMethodWithArgs:) onThread:strongSelf.webThread withObject:@[last, params] waitUntilDone:NO];
                };
            }
            NSMutableArray *trueOCArgs = [NSMutableArray array];
            for (JSValue *value in trueArgs) {
                if ([value isObject]) {
                    [trueOCArgs addObject:[value toDictionary]];
                } else if ([value isString]) {
                    [trueOCArgs addObject:[value toString]];
                } else if ([value isNull]) {
                    [trueOCArgs addObject:[NSNull null]];
                } else if ([value isBoolean]) {
                    [trueOCArgs addObject:[NSNumber numberWithBool:[value toBool]]];
                }
            }
            handler([trueOCArgs copy], ncallback);
        };
    }
}
分享给小伙伴们:
本文标签: JSBridgeXDMicroJSBri

相关文章

发表评论愿您的每句评论,都能给大家的生活添色彩,带来共鸣,带来思索,带来快乐。

CopyRight © 2015-2016 QingPingShan.com , All Rights Reserved.

清屏网 版权所有 豫ICP备15026204号