react native 0.50 源码解析 再出发 持续更新
1.核心类
1.1 RCTRootView一个RCTRootView持有一个RCTBridge成员变量 RCTRootView : UIView RCTBridge *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; @end RCTBridge.m - (Class)bridgeClass return [RCTCxxBridge class]; - (void)setUp Class bridgeClass = self.bridgeClass; self.batchedBridge = [[bridgeClass alloc] initWithParentBridge:self]; [self.batchedBridge start]; 1.3 RCTCxxBridgeRCTCxxBridge继承自RCTBridge,是RCTBridge的一个变量,拥有弱引用parentBridge指向RCTBridge变量 RCTBridge+Private.h @interface RCTCxxBridge:RCTBridge RCTCxxBridge.mm @interface RCTCxxBridge() RCTBridge *parentBridge; @end //@interface ViewController()后面 ,@end前面的是类扩展,就是创建本类中似有的属性和方法。其他类不能使用的 2.核心流程2.1 native注册模块表一个native类需要向js暴露的过程,就是向全局静态数组RCTModuleClasses注册自身class的过程。工程启动后,自动生成全局静态数组RCTModuleClasses,储存注册的class ######RCTBridge ######native类 RCT_EXPORT_MODULE宏给native类置入load函数。native类在加载过程中,可以自动向RCTModuleClasses注册自身Class。实例如下 ClassA.h #import <React/RCTBridgeModule.h> @interface ClassA <RCTBridgeModule> @end ClassA.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>> *)modules withDispatchGroup:(dispatch_group_t)dispatchGroup lazilyDiscovered:(BOOL)lazilyDiscovered NSArray<RCTModuleData *> *moduleDataById = [self registerModulesForClasses:modules]; //将modules转换成RCTCxxBridge的模块组 - (NSArray<RCTModuleData *> *)registerModulesForClasses:(NSArray<Class> *)moduleClasses for (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 发送通知RCTBridgeWillDownloadScriptNotification RCTSourceLoadBlock 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 *)script url:(NSURL *)url async:(BOOL)async dispatch_block_t completion = ^{ [self _flushPendingCalls]; 广播通知RCTJavaScriptDidLoadNotification [self ensureOnJavaScriptThread:^{ [self->_displayLink addToRunLoop:[NSRunLoop currentRunLoop]]; }]; } - (void)executeApplicationScript:(NSData *)script url:(NSURL *)url async:(BOOL)async if (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),!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]
启动 [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 成员: RCTBridge - (void)setUp URL转换 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:scriptURL runtimeBCVersion:JSNoBytecodeFileFormatVersion sourceLength:&sourceLength error:&error]; |---onComplete(nil,RCTSourceCreate(scriptURL,data,sourceLength)); + (NSData *)attemptSynchronousLoadOfBundleAtURL:(NSURL *)scriptURL runtimeBCVersion:(int32_t)runtimeBCVersion sourceLength:(int64_t *)sourceLength error:(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 *)reactTag viewName:(NSString *)viewName rootTag:(nonnull NSNumber *)rootTag props:(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++ 类 - (id)invokeWithBridge:(RCTBridge *)bridge module:(id)module arguments:(NSArray *)arguments [self processMethodSignature]; //set blocks block(bridge,index,RCTNilIfNull(json(arguments)) //set arguments [_invocation invokeWithTarget:module]; //调起函数 [_invocation getReturnValue:&returnValue]; //获取返回值 RN 支持功能 添加RN库 tabbar官方组件 TabBarIOS,TabBarIOS.Item,只支持iOS,弃用流行组件 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |