close
当前位置: 物联网在线 > 技术文库 > ios >

Weex 是如何在 iOS 客户端上跑起来的(8)

这里就可以看到,block闭包是在jsThread的线程中执行的,并非主线程。WXBridgeManager会新建一个名为@"com.taobao.weex.bridge"的jsThread线程,所有的组件注册都在这个子线程中执行的。这个jsThread也是一个单例,全局唯一。

+ (NSThread *)jsThread { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ WXBridgeThread = [[NSThread alloc] initWithTarget:[[self class]sharedManager] selector:@selector(_runLoopThread) object:nil]; [WXBridgeThread setName:WX_BRIDGE_THREAD_NAME]; if(WX_SYS_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) { [WXBridgeThread setQualityOfService:[[NSThread mainThread] qualityOfService]]; } else { [WXBridgeThread setThreadPriority:[[NSThread mainThread] threadPriority]]; } [WXBridgeThread start]; }); return WXBridgeThread; }

这里就是创建jsThread的代码,jsThread会把@selector(_runLoopThread)作为selector。

- (void)_runLoopThread { [[NSRunLoop currentRunLoop] addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode]; while (!_stopRunning) { @autoreleasepool { [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; } } }

于是这里就给jsThread开启了一个runloop。这里是用[NSMachPort port]的方式开启的runloop,之后再也无法获取到这个port了,而且这个runloop不是CFRunloop,所以用官方文档上的那3个方法已经不能停止这个runloop了,只能自己通过while的方式来停止。上述代码是一种写法,当然StackOverFlow上面推荐的是下面的写法,下面的写法也是我常用的写法。

BOOL shouldKeepRunning = YES; // global NSRunLoop *theRL = [NSRunLoop currentRunLoop]; while (shouldKeepRunning && [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]); - (void)registerComponents:(NSArray *)components { WXAssertBridgeThread(); if(!components) return; [self callJSMethod:@"registerComponents" args:@[components]]; }

在WXBridgeContext中注册组件,其实调用的是js的方法"registerComponents"。

这里有一个需要注意的一点,由于是在子线程上注册组件,那么JSFramework如果没有加载完成,native去调用js的方法,必定调用失败。所以需要在JSFramework加载完成之前,把native调用JS的方法都缓存起来,一旦JSFramework加载完成,把缓存里面的方法都丢给JSFramework去加载。

- (void)callJSMethod:(NSString *)method args:(NSArray *)args { if (self.frameworkLoadFinished) { [self.jsBridge callJSMethod:method args:args]; } else { [_methodQueue addObject:@{@"method":method, @"args":args}]; } }

所以在WXBridgeContext中需要一个NSMutableArray,用来缓存在JSFramework加载完成之前,调用JS的方法。这里是保存在_methodQueue里面。如果JSFramework加载完成,那么就会调用callJSMethod:args:方法。

- (JSValue *)callJSMethod:(NSString *)method args:(NSArray *)args { WXLogDebug(@"Calling JS... method:%@, args:%@", method, args); return [[_jsContext globalObject] invokeMethod:method withArguments:args]; }

由于这些注册的方法的定义是全局函数,那么很显然应该在JSContext的globalObject对象上调用该方法。(目前流程进行到这里还看不到定义的全局函数,往后看就会看到)

还是用WXWebComponent来举例,那么这里注册组件的method就是@“registerComponents”,args参数如下:

( { append = tree; methods = ( goForward, goBack, reload ); type = web; } )

实际上程序运行到这里,并不会去执行callJSMethod:args:,因为现在JSFramework还没有加载完成。

注册组件的全部流程如下:

Weex 是如何在 iOS 客户端上跑起来的

再注册Modules

Weex 是如何在 iOS 客户端上跑起来的

注册Modules的流程和上面注册Components非常类似。

+ (void)_registerDefaultModules { [self registerModule:@"dom" withClass:NSClassFromString(@"WXDomModule")]; [self registerModule:@"navigator" withClass:NSClassFromString(@"WXNavigatorModule")]; [self registerModule:@"stream" withClass:NSClassFromString(@"WXStreamModule")]; [self registerModule:@"animation" withClass:NSClassFromString(@"WXAnimationModule")]; [self registerModule:@"modal" withClass:NSClassFromString(@"WXModalUIModule")]; [self registerModule:@"webview" withClass:NSClassFromString(@"WXWebViewModule")]; [self registerModule:@"instanceWrap" withClass:NSClassFromString(@"WXInstanceWrap")]; [self registerModule:@"timer" withClass:NSClassFromString(@"WXTimerModule")]; [self registerModule:@"storage" withClass:NSClassFromString(@"WXStorageModule")]; [self registerModule:@"clipboard" withClass:NSClassFromString(@"WXClipboardModule")]; [self registerModule:@"globalEvent" withClass:NSClassFromString(@"WXGlobalEventModule")]; [self registerModule:@"canvas" withClass:NSClassFromString(@"WXCanvasModule")]; [self registerModule:@"picker" withClass:NSClassFromString(@"WXPickerModule")]; [self registerModule:@"meta" withClass:NSClassFromString(@"WXMetaModule")]; [self registerModule:@"webSocket" withClass:NSClassFromString(@"WXWebSocketModule")]; }
(责任编辑:ioter)

用户喜欢...

设计实例 #8:如何在整个热电偶测量范围内检测热电偶并准确检测温度

热电偶参考设计演示了如何在整个热电偶测量范围内检测热电偶并准确检测温度。 该解决方案使用MCP3421 18位模数转换器(ADC)测量热电偶两端的电压。ADC具有内部2.048V基准电压和可编程增益放...


如何在零信任世界中保护医疗保健物联网设备

ISTOCK 目前全球安装了超过1亿台医疗保健物联网设备,到2020年增长到1.61亿,根据Statista的数据,在短短三年内实现了17.2%的复合年增长率(CAGR)。 据埃森哲2017年健康互联网称,医疗保健管理...


如何在便携式设计的电池容量读数中实现更高的准确性

我的狗摩卡(图1)经常喜欢在徒步旅行期间跑到我前面进行一些越野探索。她总是在以后找到我,但有时我开始寻找她很久,所以我想找到一种方法来轻松追踪她的位置。通过Adafruit的展望网站...


数字双胞胎如何在物联网支持的环境中推动创新

动态数字表示或数字双胞胎正在迅速改变行业设计,构建和操作其产品和流程的方式。Gartner预测,到2021年,一半的大型工业公司将使用数字双子机,从而使这些机构的有效性得到10%的提高。...


电动汽车绝缘电阻如何在线检测?

电动汽车是一个复杂的机电一体化产品,其中的许多部件包括动力电池、电机、充电机、能量回收装置、辅助电池充...


对话赛灵思:33年老牌芯片厂如何在AI浪潮里新兴业务年增46%

随着移动互联网红利日渐式微,一个更具备颠覆性、更具备革命性的王朝正悄然来临——人工智能(AI)。在下一个十年里,云计算、机器学习、AI芯片等相关产业将以迅猛的势头持续占领市...


客户投诉器件功耗太大,“元凶”原来是它!

selina 在 周五, 11/24/2017 - 09:48 提交 为什么我的处理器功耗大于数据手册给出的值? 在之前的文章中,我们谈到了一个功耗过小的器件——是的,的确有这种情况——带来麻烦的事情。但这种...


SaaS:从功能、数据到生态以及客户成功的一场变革

不知不觉“终结软件”的呐喊已经走过了近二十年,SaaS已经走进千家万户,人们不再纠结是否要“终结软件”,也没...


华为客户荣获2017全球智慧城市博览会两项大奖两项提名奖

在2017年全球智慧城市博览会上,华为在智慧城市领域的四位客户以他们在提供高质量市民服务、实现可持续发展方面...


迈来芯宣布上线中文官方网站以加速融入中国市场,更好的服务中国客户

全球微电子技术公司——迈来芯(Melexis)宣布,定于2017年11月正式上线中文官方网站。迈来芯电子科技(上海)有限...