iOS.ReactNative-3-about-viewmanager-uimanager-and-bridgemodule
RCTViewManager and RCTUIManager
1. RCTViewManager
1.1 RCTViewManager 实现了接口RCTBridgeModule
@interface RCTViewManager : NSObject <RCTBridgeModule>
1.2 宏RCT_EXPORT_VIEW_PROPERTY
from file RCTViewManager.m
RCT_EXPORT_VIEW_PROPERTY(accessibilityLabel, NSString)
以上宏展开为:
// RCT_EXPORT_VIEW_PROPERTY(accessibilityLabel, NSString)
+ (NSString *)getPropConfigView_accessibilityLabel { return @"NSString"; }
- (void)set_accessibilityLabel:(id)json forView:(UIView *)view withDefaultView:(UIView *)defaultView
{ if ((json && !RCTSetProperty(view, @"accessibilityLabel", @selector(NSString:), json))
|| (!json && !RCTCopyProperty(view, defaultView, @"accessibilityLabel")))
{
do {
if (RCTLogLevelError >= RCTLogLevelMustFix) {
do {
BOOL pass = ((__objc_no) != );
if ( && !pass){
[[NSAssertionHandler currentHandler] handleFailureInFunction:@(__func__)
file:@("/Users/XiaoKL/react-native/AwesomeProject/node_modules/react-native/React/Views/RCTViewManager.m")
lineNumber:
description:@"%@ does not have setter for `%s` property", [view class], "accessibilityLabel"];
}
_RCTAssertFormat(pass, "/Users/XiaoKL/react-native/AwesomeProject/node_modules/react-native/React/Views/RCTViewManager.m",
, __func__,
@"%@ does not have setter for `%s` property",
[view class], "accessibilityLabel");
} while ();
}
_RCTLogFormat(RCTLogLevelError, "/Users/XiaoKL/react-native/AwesomeProject/node_modules/react-native/React/Views/RCTViewManager.m", , @"%@ does not have setter for `%s` property",
[view class], "accessibilityLabel");
} while ();
}
}
3. RCTBridgeModule接口
/**
* Provides the interface needed to register a bridge module.
*/
@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)
void RCTRegisterModule(Class moduleClass)
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
RCTModuleClasses = [[NSMutableArray alloc] init];
}); RCTAssert([moduleClass conformsToProtocol:@protocol(RCTBridgeModule)], // 1
@"%@ does not conform to the RCTBridgeModule protocol",
NSStringFromClass(moduleClass)); // Register module
[RCTModuleClasses addObject:moduleClass];
}
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中的接口:
RCT_EXPORT_METHOD(createTimer:(NSNumber *)callbackID
duration:(NSTimeInterval)jsDuration
jsSchedulingTime:(NSDate *)jsSchedulingTime
repeats:(BOOL)repeats)
以上宏 RCT_EXPORT_METHOD()展开为:
+ (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)。
/* MyModuleExport.m:
*
* #import "RCTBridgeModule.h"
*
* @interface RCT_EXTERN_MODULE(MyModule, NSObject)
*
* RCT_EXTERN_METHOD(doSomething:(NSString *)string withFoo:(NSInteger)a bar:(NSInteger)b)
*
* @end
*
* This will now expose MyModule and the method to JavaScript via
* `NativeModules.MyModule.doSomething`
*/
#define RCT_EXTERN_MODULE(objc_name, objc_supername) \
RCT_EXTERN_REMAP_MODULE(, objc_name, objc_supername) /**
* Like RCT_EXTERN_MODULE, but allows setting a custom JavaScript name.
*/
#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)
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
iOS.ReactNative-3-about-viewmanager-uimanager-and-bridgemodule的更多相关文章
- iOS React-Native入门指南之HelloWorld
React-native 作为facebook开源项目,最近是火的一塌糊涂,它采用node.js能够写ios和android的native界面代码,简直是太酷了.支持动态更新,而且appstore 提 ...
- 新闻头条应用源码ios版
<ignore_js_op> 源码下载:http://code.662p.com/view/13343.html 作者ymcao,源码TopNewsIOS,新闻头条IOS ...
- React-Native入门指南之HelloWorld
iOS React-Native入门指南之HelloWorld React-native 作为facebook开源项目,最近是火的一塌糊涂,它采用node.js能够写ios和android的nativ ...
- React Native之code-push的热更新(ios android)
React Native之code-push的热更新(ios android) React Native支持大家用React Native技术开发APP,并打包生成一个APP.在动态更新方面React ...
- react-native开发总结
项目地址:http://liu12fei08fei.github.io/blog/41react-native.html 说明 • 项目总结代码地址 • 从项目开始启动(2018-07-02)到项目进 ...
- react-native 常用命令
创建项目 react-native init AwesomeProject //AwesomeProject是项目名 启动 Node.js web server react-native start ...
- React Native环境配置
React Native环境配置 史上最全Windows版本搭建安装React Native环境配置 配置过React Native 环境的都知道,在Windows React Native环境配置有 ...
- window环境下搭建react native及相关插件
可以先浏览一下中文翻译的开发文档具体了解一下关于React Native,想要查看官方文档可以点http://facebook.github.io/react-native/docs/getting- ...
- React Native获取组件位置和大小
RN页面中定位或滚动操作时,需要获取元素的大小和位置信息,有几种常用的方法 获取设备屏幕的宽高 import {Dimensions} from 'react-native'; var {height ...
- CodePush热更新组件详细接入教程
CodePush热更新组件详细接入教程 什么是CodePush CodePush是一个微软开发的云服务器.通过它,开发者可以直接在用户的设备上部署手机应用更新.CodePush相当于一个中心仓库,开发 ...
随机推荐
- MongoDB(八)Mongodb——GridFS存储
mongoDB的文档以BSON格式存储,支持二进制的数据类型,当我们把二进制格式的数据直接保存到mongoDB的文档中.但是当文件太大时,例如图片和视频等文件,每个文档的长度是有限的,于是mongoD ...
- Windows 2008 R2 安装 Windows phone 7 开发环境
安装环境:1.Windows server 2008 R22.Visual Studio 2010 SP1 旗舰版 1.下载 WP7 SDK 离线安装包.(话说要选择与 VS2010 相同语言的版本) ...
- 8、SQL Server 表分区
什么是表分区?表分区其实就是将一个大表分成若干个小表.表分区可以从物理上将一个大表分成几个小表,但是逻辑上还是一个表.所以当执行插入.更新等操作的时候,不需要我们去判断应该插入或更新到哪个表中.只需要 ...
- SIGABRT的可能原因
常见原因: 第三方库如glic检测到内部错误或者破坏约束条件 3种可能1.double free/free 没有初始化的地址或者错误的地址2.堆越界3.assert
- lambda匿名函数
1.python中的匿名函数的格式 lambda arg1,arg2...,argN:expression (lambda关键字后,冒号":"前是参数,多个参数用逗号&qu ...
- Eclipse中web项目部署至Tomcat【转】
Eclipse的web工程至Tomcat默认的部署目录是在工程空间下,本文旨在将部署目录改为Tomcat安装目录,并解决依赖包输出问题. 1.在Eclipse中添加Tomcat服务器. 2.将web ...
- 在spring框架中配置Quartz定时器发生错误: class org.springframework.scheduling.quartz.JobDetailBean has interface org.quartz.JobDetail as sup
这是由于spring和Quartz的不兼容性造成的.我的spring是4.0.2,但是Quartz是2.2.3的,换了一个1.8版本的Quartz就解决问题了.
- 时间服务器:NTP 服务器
15.1 关于时区与网络校时的通讯协议 使得每一部主机的时间同步化. DHCP 客户端/服务器端所需要的租约时间限制. 网络侦测时所需要注意的时间点.刚刚谈到的登录文件分析功能.具有相关性的主 ...
- 需要交互的shell编程——EOF(转载)
在shell编程中,”EOF“通常与”<<“结合使用,“<<EOF“表示后续的输入作为子命令或子shell的输入,直到遇到”EOF“, 再次返回到主调shell,可将其理解为分 ...
- VFP不同句柄 同一事务处理 统一提交或回滚
SQLSetprop(m.lnAccHandle,[Transactions],2)SQLSetprop(m.lnSetHandle,[Transactions],2) SQLSetprop(m.ln ...