1.核心类

1.1 RCTRootView

一个RCTRootView持有一个RCTBridge成员变量

RCTRootView : UIViewRCTBridge *bridge;UIViewController *reactViewController;UIView *contentView;UIView *loadingView;

1.2 RCTBridge

一个RCTBridge持有一个RCTCxxBridge成员变量

RCTBridge.h@interface RCTBridge : NSObject <RCTInvalidating>RCTBridge+Private.h
@interface RCTBridge ()RCTBridge *batchedBridge;
@endRCTBridge.m
- (Class)bridgeClassreturn [RCTCxxBridge class];- (void)setUpClass bridgeClass = self.bridgeClass;self.batchedBridge = [[bridgeClass alloc] initWithParentBridge:self];[self.batchedBridge start];

1.3 RCTCxxBridge

RCTCxxBridge继承自RCTBridge,是RCTBridge的一个变量,拥有弱引用parentBridge指向RCTBridge变量

RCTBridge+Private.h
@interface RCTCxxBridge:RCTBridgeRCTCxxBridge.mm
@interface RCTCxxBridge()
RCTBridge *parentBridge;
@end
//@interface ViewController()后面 ,@end前面的是类扩展,就是创建本类中似有的属性和方法。其他类不能使用的

2.核心流程

2.1 native注册模块表

一个native类需要向js暴露的过程,就是向全局静态数组RCTModuleClasses注册自身class的过程。工程启动后,自动生成全局静态数组RCTModuleClasses,储存注册的class

######RCTBridge
声明全局静态数组:
static NSMutableArray<Class> *RCTModuleClasses;

######native类
需要做到以下两点,
1.实现RCTBridgeModule协议
2.在m文件中放置RCT_EXPORT_MODULE()代码。

RCT_EXPORT_MODULE宏给native类置入load函数。native类在加载过程中,可以自动向RCTModuleClasses注册自身Class。实例如下

ClassA.h
#import <React/RCTBridgeModule.h>
@interface ClassA <RCTBridgeModule>
@endClassA.m
RCT_EXPORT_MODULE() ==>
extern __attribute__((visibility("default")))
void RCTRegisterModule(Class);
+ (void)load { RCTRegisterModule(self); }========================================
宏定义
RCTBridgeModule.h
#define RCT_EXPORT_MODULE(js_name) \
RCT_EXTERN void RCTRegisterModule(Class); \
+ (NSString *)moduleName { return @#js_name; } \
+ (void)load { RCTRegisterModule(self); }#define RCT_EXPORT_MODULE(js_name) RCT_EXTERN void RCTRegisterModule(Class);  + (NSString *)moduleName { return @#js_name; }  + (void)load { RCTRegisterModule(self); }RCTDefindes.h
#define RCT_EXTERN extern __attribute__((visibility("default")))注册
RCTBridge.m
static NSMutableArray<Class> *RCTModuleClasses;
void RCTRegisterModule(Class moduleClass)[RCTModuleClasses addObject:moduleClass];

2.2 RCTCxxBridge初始化模块表

RCTCxxBridge有三个成员变量,_moduleDataByName,_moduleDataByID,_moduleClassesByID

RCTCxxBridge
NSMutableDictionary<NSString *, RCTModuleData *> *_moduleDataByName; //字典,name:RCTModuleData键值对
NSMutableArray<RCTModuleData *> *_moduleDataByID; //RCTModuleData数组
NSMutableArray<Class> *_moduleClassesByID; //Class数组
- (void)start [self _initModules:RCTGetModuleClasses() withDispatchGroup:prepareBridge lazilyDiscovered:NO];- (void)_initModules:(NSArray<id<RCTBridgeModule>> *)moduleswithDispatchGroup:(dispatch_group_t)dispatchGrouplazilyDiscovered:(BOOL)lazilyDiscoveredNSArray<RCTModuleData *> *moduleDataById = [self registerModulesForClasses:modules]; //将modules转换成RCTCxxBridge的模块组- (NSArray<RCTModuleData *> *)registerModulesForClasses:(NSArray<Class> *)moduleClassesfor (Class moduleClass in moduleClasses) {_moduleDataByName[moduleName] = moduleData;[_moduleClassesByID addObject:moduleClass];[moduleDataByID addObject:moduleData];}[_moduleDataByID addObjectsFromArray:moduleDataByID];

2.3 RCTCxxBridge 加载/执行JS资源

 - (void)start [self loadSource:^(NSError *error, RCTSource *source){sourceCode = source.data;}]  // 加载JS[strongSelf executeSourceCode:sourceCode sync:NO]; //执行JS- (void)loadSource:(RCTSourceLoadBlock)_onSourceLoad onProgress:(RCTSourceLoadProgressBlock)onProgress发送通知RCTBridgeWillDownloadScriptNotificationRCTSourceLoadBlock onSourceLoad = ^(NSError *error, RCTSource *source) {发送通知RCTBridgeDidDownloadScriptNotification:RCTSource}[RCTJavaScriptLoader loadBundleAtURL:self.bundleURL onProgress:onProgress onComplete:^(NSError *error, RCTSource *source){onSourceLoad(error, source);}- (void)executeSourceCode:(NSData *)sourceCode sync:(BOOL)sync- (void)executeApplicationScript:(NSData *)scripturl:(NSURL *)urlasync:(BOOL)asyncdispatch_block_t completion = ^{[self _flushPendingCalls];广播通知RCTJavaScriptDidLoadNotification[self ensureOnJavaScriptThread:^{[self->_displayLink addToRunLoop:[NSRunLoop currentRunLoop]];}];}- (void)executeApplicationScript:(NSData *)scripturl:(NSURL *)urlasync:(BOOL)asyncif (isRAMBundle(script))self->_reactInstance->loadRAMBundle(std::move(registry), std::move(scriptStr),sourceUrlStr.UTF8String, !async);else if (self->_reactInstance)self->_reactInstance->loadScriptFromString(std::make_unique<NSDataBigString>(script),sourceUrlStr.UTF8String, !async);- (void)registerAdditionalModuleClasses:(NSArray<Class> *)modules|=== - (NSArray<RCTModuleData *> *)registerModulesForClasses:(NSArray<Class> *)moduleClasses|---for (Class moduleClass in moduleClasses) {NSString *moduleName = RCTBridgeModuleNameForClass(moduleClass);moduleData = [[RCTModuleData alloc] initWithModuleClass:moduleClass bridge:self];}[RCTCxxBridge registerExtraModules]
  • (void)start
    |--- 广播通知---
    RCTJavaScriptWillStartLoadingNotification:@{@"bridge": self}
    |--- 新建并启动js线程 _jsThread
    |--- 注册moduleClass---
    [self registerExtraModules];
    [self _initModules:RCTGetModuleClasses() withDispatchGroup:prepareBridge lazilyDiscovered:NO];
    |--- 创建工厂并配置---
    std::shared_ptr<JSExecutorFactory> executorFactory;
    |--- 加载js资源---
    [self loadSource:^(NSError error, RCTSource source)
    |--- 执行js---
    [strongSelf executeSourceCode:sourceCode sync:NO];

启动

[AppDelegate didFinishLaunchingWithOptions]
|---获取jsCodeLocation
|---[RCTRootView initWithBundleURL..]|---[RCTBridge alloc+init]|---设置变量:delegate,bundleURL,moduleProvider, launchOptions|---[RCTBridge setUp]|---设置变量:bundleURL|---[RCTCxxBridge alloc+init]  --> RCTBridge.batchedBridge|---[RCTCxxBridge start]|---[RCTRootView initWithBridge:...]|---注册三个通知,如下|---[self bundleFinishedLoading:([_bridge batchedBridge] ?: _bridge)];|---RCTRootContentView alloc|---[self runApplication:bridge];|---[bridge enqueueJSCall:@"AppRegistry"method:@"runApplication"args:@[moduleName, appParameters]completion:NULL];|---insertSubview:_contentView

RCTRootView 继承自UIView,内含RCTBridge变量,初始化参数BundleURL/moduleName/Properties/launchOptions。初始化的时候,初始化RCTBridge变量,自我初始化。自我初始化过程:注册三个通知,RCTJavaScriptWillStartLoadingNotification/RCTJavaScriptDidLoadNotification/RCTContentDidAppearNotification

RCTBridge native call js

[RCTBridge enqueueJSCall:(NSString *)module method:(NSString *)method args:(NSArray *)args completion:(dispatch_block_t)completion]
|---[self.batchedBridge enqueueJSCall:module method:method args:args completion:completion];

RCTCxxBridge 成员:
_moduleClassesByID
_moduleDataByID
_moduleDataByName 可变字典:string(moduleName):RCTModuleData(Data)的键值队
RCTCxxBridge native call js,可以从任意线程中调起

RCTBridge
- (void)setUpURL转换self.batchedBridge = [[bridgeClass alloc] initWithParentBridge:self];[self.batchedBridge start];- (void)registerAdditionalModuleClasses:(NSArray<Class> *)modules[self.batchedBridge registerAdditionalModuleClasses:modules];
RCTJavaScriptLoader
+ (void)loadBundleAtURL:(NSURL *)scriptURL onProgress:(RCTSourceLoadProgressBlock)onProgress onComplete:(RCTSourceLoadBlock)onComplete
|---NSData *data = [self attemptSynchronousLoadOfBundleAtURL:scriptURLruntimeBCVersion:JSNoBytecodeFileFormatVersionsourceLength:&sourceLengtherror:&error];
|---onComplete(nil, RCTSourceCreate(scriptURL, data, sourceLength));+ (NSData *)attemptSynchronousLoadOfBundleAtURL:(NSURL *)scriptURLruntimeBCVersion:(int32_t)runtimeBCVersionsourceLength:(int64_t *)sourceLengtherror:(NSError **)error
|---FILE *bundle = fopen(scriptURL.path.UTF8String, "r");size_t readResult = fread(&header, sizeof(header), 1, bundle);
[RCTCxxBridge enqueueJSCall:(NSString *)module method:(NSString *)method args:(NSArray *)args completion:(dispatch_block_t)completion]
|---

NSInvocation 调用 native 方法

调用原生代码生成UI控件

RCTUIManager RCT_EXPORT_METHOD(createView:(nonnull NSNumber *)reactTagviewName:(NSString *)viewNamerootTag:(nonnull NSNumber *)rootTagprops:(NSDictionary *)props)
|---createViewBlock|---[RCTComponentData createViewWithTag:reactTag];|--- [self.manager view]   #此处self.manager是实际需要生成的UI类,如RCTTextView等#所以,所有RN的原生UI都必须实现view功能|---RCTUIManager->_viewRegistry[reactTag] = preliminaryCreatedView;  #保存至注册数组,reactTag:preliminaryCreatedView#RCTUIManager->_viewRegistry # {1 = "<RCTRootContentView: 0x7faf12c015d0; reactTag: 1; frame = (0 0; 414 736); gestureRecognizers = <NSArray: 0x60000024eaf0>; layer = <CALayer: 0x6040002376c0>>";# 2 = "<UIView: 0x7faf12f0a6d0; frame = (0 0; 0 0); layer = <CALayer: 0x600000621300>>";}
Instance C++ 类
void Instance::loadRAMBundle(std::unique_ptr<RAMBundleRegistry> bundleRegistry,std::unique_ptr<const JSBigString> startupScript,std::string startupScriptSourceURL,bool loadSynchronously)

RCTModuleMethod C++ 类
通过NSInvocation动态调用相应的OC模块方法

- (id)invokeWithBridge:(RCTBridge *)bridgemodule:(id)modulearguments:(NSArray *)arguments[self processMethodSignature];   //set blocks block(bridge, index, RCTNilIfNull(json(arguments))   //set arguments[_invocation invokeWithTarget:module];   //调起函数[_invocation getReturnValue:&returnValue];   //获取返回值

RN 支持功能
tabbar,nagigator,text,image,数据库?,ar?,真机调试日志?,网络,摄像头拍照,图片剪裁,音频,视频,下载,

添加RN库

tabbar
官方组件 TabBarIOS,TabBarIOS.Item,只支持iOS,弃用
流行组件

转载于:https://blog.51cto.com/7324086/2128523

react native 0.50 源码解析 再出发 持续更新相关推荐

  1. React深入学习与源码解析笔记

    ***当前阶段的笔记 *** 「面向实习生阶段」https://www.aliyundrive.com/s/VTME123M4T9 提取码: 8s6v 点击链接保存,或者复制本段内容,打开「阿里云盘」 ...

  2. React Native 0.50版本新功能简介

    React Native在2017年经历了众多版本的迭代,从本人接触的0.29版本开始,到前不久发布的0.52版本,React Native作为目前最受欢迎的移动跨平台方案.虽然,目前存在着很多的功能 ...

  3. Android8.0 bindService源码解析

    1.AMS的bindService 我们从调用bindService方法开始来看 bindService(intent,serviceConnection, Context.BIND_AUTO_CRE ...

  4. Android7.0 bindService源码解析

    看到标题的时候,有些同学可能会有些质疑:现在都Android12了,你讲Android7,是不是太过时了.这里有两个原因: (1)Android8.0和Android7.0的源码有些不同,但是Andr ...

  5. React Native 启动流程 源码剖析

    开始之前   开始分析之前,新建一个名为 RnDemo 的空项目,RN 版本选择 0.58.1,查看项目自动为我们生成 MainActivity.java 和 MainApplication.java ...

  6. react redux 简化_Redux 源码解析

    前言 近日,出于对 Redux 的好奇和想对自己用过的东西知根知底之目的,做了一个 Redux 的自我检测,以便彻底了解其精髓之处.下面我会对使用 Redux 之后产生的疑问做一个清单,用问题导向往下 ...

  7. 部署测试fabric1.0及源码解析

    开发环境 UBUNTU 16.04 LTS docker docker-compose git go 1.8以上 docker,docker-compose以及go的安装这里不再描述. 部署测试 新建 ...

  8. android9.0 UsbService源码解析

    文章目录 前言 一.服务启动 二.服务创建 三.系统就绪 四.系统启动完毕 前言 USBManager作为一接口类,客户端,当然要有一个服务端来支持工作,这个服务就是UsbService.我这里先从他 ...

  9. YYModel V1.0.4源码解析

    YYKit出现了很长时间了,一直想要详细解析一下它的源码,都是各种缘由推迟了. 最近稍微闲了一点,决定先从最简单的YYModel开始吧. 首先,我也先去搜索了一下YYModel相关的文章,解析主要AP ...

最新文章

  1. 多线程中使用mktime和setenv函数
  2. C/C++操作符的优先级和结合性问题浅析
  3. Scrapy 模拟登陆知乎--抓取热点话题
  4. 【知识星球】重要小结与涨价预告
  5. python写linux脚本_Linux下设置python脚本文件为服务
  6. vs 2012 控制台自动关闭
  7. 深入解读无服务器架构下的数据库
  8. 微软.NET Framework 4.5.2 RTM正式版
  9. Swift中文教程(十四) 初始化
  10. 【Python】Python3.7.3 - Python命令行参数详解
  11. Activity与Service之间交互并播放歌曲
  12. FMEA失效模式和影响分析中措施优先级AP值的方法
  13. IAR EWARM教程
  14. Spring-Boot开发者工具:自动重启、LiveReload、远程开发、默认的开发时属性值
  15. win7安装镜像注入USB3.0,NVMe驱动
  16. 最好用的屏幕录像软件录制教程分享
  17. 黑马程序员--IO总结(含2个设计模式)
  18. 天行健,君子以自强不息;地势坤,君子以厚德载物的解释
  19. 上了年纪的酒店,如何“鸟枪换炮”?
  20. HDU-1253-胜利大逃亡

热门文章

  1. 通过实现IHttpModule初始化Nhibernate的Session
  2. Adobe MasterCollection CS5 试用版下载链接
  3. 基于Bmob从零开始写一个博客小程序
  4. malloc函数的使用以及内存泄露情况
  5. Oracle脚本(二)
  6. tcp udp区别优缺点_TCP和UDP的区别
  7. Setting下的自定义控件LinearColorBar
  8. CHD4B1(hadoop-0.23)实现NameNode HA安装配置
  9. vmware上的ubuntu与window共享folder(shared folder disabled.)
  10. ThreadLocal线程本地存储