iOS.ReactNative-3-about-viewmanager-uimanager-and-bridgemodule
RCTViewManager and RCTUIManager
1. RCTViewManager
1.1 RCTViewManager 实现了接口RCTBridgeModule
1 @interface RCTViewManager : NSObject <RCTBridgeModule>
1.2 宏RCT_EXPORT_VIEW_PROPERTY
from file RCTViewManager.m
1 RCT_EXPORT_VIEW_PROPERTY(accessibilityLabel, NSString)
以上宏展开为:
1 // RCT_EXPORT_VIEW_PROPERTY(accessibilityLabel, NSString) 2 + (NSString *)getPropConfigView_accessibilityLabel { return @"NSString"; } 3 - (void)set_accessibilityLabel:(id)json forView:(UIView *)view withDefaultView:(UIView *)defaultView 4 { if ((json && !RCTSetProperty(view, @"accessibilityLabel", @selector(NSString:), json)) 5 || (!json && !RCTCopyProperty(view, defaultView, @"accessibilityLabel"))) 6 { 7 do { 8 if (RCTLogLevelError >= RCTLogLevelMustFix) { 9 do { 10 BOOL pass = ((__objc_no) != 0); 11 if (1 && !pass){ 12 [[NSAssertionHandler currentHandler] handleFailureInFunction:@(__func__) 13 file:@("/Users/XiaoKL/react-native/AwesomeProject/node_modules/react-native/React/Views/RCTViewManager.m") 14 lineNumber:94 15 description:@"%@ does not have setter for `%s` property", [view class], "accessibilityLabel"]; 16 } 17 _RCTAssertFormat(pass, "/Users/XiaoKL/react-native/AwesomeProject/node_modules/react-native/React/Views/RCTViewManager.m", 18 94, __func__, 19 @"%@ does not have setter for `%s` property", 20 [view class], "accessibilityLabel"); 21 } while (0); 22 } 23 _RCTLogFormat(RCTLogLevelError, "/Users/XiaoKL/react-native/AwesomeProject/node_modules/react-native/React/Views/RCTViewManager.m", 94, @"%@ does not have setter for `%s` property", 24 [view class], "accessibilityLabel"); 25 } while (0); 26 } 27 }
3. RCTBridgeModule接口
1 /** 2 * Provides the interface needed to register a bridge module. 3 */ 4 @protocol RCTBridgeModule <NSObject>
RCTBridgeModule: 定义注册一个“bridge module”所需要的接口。
bridge module: 实现接口RCTBridgeModule的类被称为“bridge module”, 这些模块可以被注册到 RCTBridge 中。
3.1 RCTBridgeModule.h中提供的宏定义
宏 | 宏定义以及描述 |
RCT_EXPORT_MODULE(js_name) |
#define RCT_EXPORT_MODULE(js_name) \ RCT_EXTERN void RCTRegisterModule(Class); \ + (NSString *)moduleName { return @#js_name; } \ + (void)load { RCTRegisterModule([self class]); } |
RCT_EXPORT_METHOD(method) |
#define RCT_EXPORT_METHOD(method) \ RCT_REMAP_METHOD(, method) |
RCT_REMAP_METHOD(js_name, method) |
#define RCT_REMAP_METHOD(js_name, method) \ RCT_EXTERN_REMAP_METHOD(js_name, method) \ - (void)method |
RCT_EXTERN_MODULE(objc_name, objc_supername) |
#define RCT_EXTERN_MODULE(objc_name, objc_supername) \ RCT_EXTERN_REMAP_MODULE(, objc_name, objc_supername) |
RCT_EXTERN_REMAP_MODULE(js_name, objc_name, objc_supername) |
#define RCT_EXTERN_REMAP_MODULE(js_name, objc_name, objc_supername) \ objc_name : objc_supername \ @end \ @interface objc_name (RCTExternModule) <RCTBridgeModule> \ @end \ @implementation objc_name (RCTExternModule) \ RCT_EXPORT_MODULE(js_name) |
RCT_EXTERN_METHOD(method) |
#define RCT_EXTERN_METHOD(method) \ RCT_EXTERN_REMAP_METHOD(, method) |
RCT_EXTERN_REMAP_METHOD(js_name, method) |
#define RCT_EXTERN_REMAP_METHOD(js_name, method) \ + (NSArray *)RCT_CONCAT(__rct_export__, RCT_CONCAT(js_name, RCT_CONCAT(__LINE__, __COUNTER__))) { \ return @[@#js_name, @#method]; \ } \ |
A): RCT_EXPORT_MODULE(js_name): 将BridgeModule注册到bridge中。该宏依赖函数:
RCTRegisterModule(), 下面看一下该函数的实现: (RCTBridge.m)
1 void RCTRegisterModule(Class moduleClass) 2 { 3 static dispatch_once_t onceToken; 4 dispatch_once(&onceToken, ^{ 5 RCTModuleClasses = [[NSMutableArray alloc] init]; 6 }); 7 8 RCTAssert([moduleClass conformsToProtocol:@protocol(RCTBridgeModule)], // 1 9 @"%@ does not conform to the RCTBridgeModule protocol", 10 NSStringFromClass(moduleClass)); 11 12 // Register module 13 [RCTModuleClasses addObject:moduleClass]; 14 }
RCTRegisterModule()仅仅是将Class对象添加到了一个数组类型的静态变量RCTModuleClasses中.
1: “bridge module” 必须实现接口 RCTBridgeModule 。
RCT_EXPORT_MODULE(js_name)
"The optional js_name argument will be used as the JS module name. If omitted, the JS module name will
match the Objective-C class name. "
B): RCT_EXPORT_METHOD(method) 宏
Wrap the parameter line of your method implementation with this macro to
expose it to JS.
用宏 RCT_EXPORT_METHOD() 来处理要导出到JS中的接口:
1 RCT_EXPORT_METHOD(createTimer:(NSNumber *)callbackID 2 duration:(NSTimeInterval)jsDuration 3 jsSchedulingTime:(NSDate *)jsSchedulingTime 4 repeats:(BOOL)repeats)
以上宏 RCT_EXPORT_METHOD()展开为:
1 + (NSArray *)__rct_export__1720 { return @[@"", @"createTimer:(NSNumber *)callbackID duration:(NSTimeInterval)jsDuration jsSchedulingTime:(NSDate *)jsSchedulingTime repeats:(BOOL)repeats"]; }
- (void)createTimer:(NSNumber *)callbackID duration:(NSTimeInterval)jsDuration jsSchedulingTime:(NSDate *)jsSchedulingTime repeats:(BOOL)repeats
导入到JS的接口为: "NativeModules.ModuleName.createTimer(number)", 只有Selector第一个:以前的部分。
TODO: JavaScript Promise Javascript.Promise
C): RCT_REMAP_METHOD(js_name, method) 宏
该宏和RCT_EXPORT_METHOD(method)类似, 只不过通过该宏可以指定导入到JS的接口名称。
D): 宏 RCT_EXTERN_MODULE 和 RCT_EXTERN_REMAP_MODULE
RCT_EXTERN_MODULE(objc_name, objc_supername)
RCT_EXTERN_REMAP_MODULE(js_name, objc_name, objc_supername)
"Use this macro in a private Objective-C implementation file to automatically register an
external module with the bridge when it loads." 'private Object-C implementation'是指Objective-C中的类别(category)。
1 2 /* MyModuleExport.m: 3 * 4 * #import "RCTBridgeModule.h" 5 * 6 * @interface RCT_EXTERN_MODULE(MyModule, NSObject) 7 * 8 * RCT_EXTERN_METHOD(doSomething:(NSString *)string withFoo:(NSInteger)a bar:(NSInteger)b) 9 * 10 * @end 11 * 12 * This will now expose MyModule and the method to JavaScript via 13 * `NativeModules.MyModule.doSomething` 14 */ 15 #define RCT_EXTERN_MODULE(objc_name, objc_supername) \ 16 RCT_EXTERN_REMAP_MODULE(, objc_name, objc_supername) 17 18 /** 19 * Like RCT_EXTERN_MODULE, but allows setting a custom JavaScript name. 20 */ 21 #define RCT_EXTERN_REMAP_MODULE(js_name, objc_name, objc_supername) \ 22 objc_name : objc_supername \ 23 @end \ 24 @interface objc_name (RCTExternModule) <RCTBridgeModule> \ 25 @end \ 26 @implementation objc_name (RCTExternModule) \ 27 RCT_EXPORT_MODULE(js_name)
E: 宏RCT_EXTERN_METHOD 和 RCT_EXTERN_REMAP_METHOD
略
3.2 RCTBridgeModule的接口方法
RCTBridgeModule提供的接口用来注册"Bridge Module" 模块。
3.3 实现RCTBridgeModule接口的类
实现接口RCTBridgeModule的类都是 "Bridge Module" 模块类,这些类的实例称为"Bridge Module"。
3.4 "Bridge Module" 初始化
RCTBatchedBridge类的方法initModules 对Native "Bridge Module" 进行了初始化。
Reference
1. React-Native Source Code