根据官方文档实现一个Fabric组件最少需要做三件步骤:
1. 定义一个JavaScript specifications
相当于定义一套接口规范给js和c++,使2边用一同一套接口,C++的接口文件是通过CodeGen工具脚本生成
ts文件方式定义遇到的问题:
- 对象需要定义成Readonly
- 数组需要定义成ReadonlyArray
- OC中的枚举在ts中一般通过type定义为字符串类型
type StrokeColors = ReadonlyArray<ColorValue>
type LineDashPattern = ReadonlyArray<Int32>
type MapEvent = Readonly<{
coordinate: {
latitude: Double;
longitude: Double;
};
position: {
x: Float;
y: Float;
};
action: string;
id?: string;
}>;
type CGLineCap =
| 'butt'
| 'round'
| 'square';
type CGLineJoin =
| 'miter'
| 'round'
| 'bevel';
type LatLng = Readonly<{
latitude: Double;
longitude: Double;
}>;
type LatLngs = ReadonlyArray<LatLng>
interface AIRMapPolylineProps extends ViewProps {
coordinates: LatLngs;
strokeColor?: ColorValue;
strokeColors?: StrokeColors;
strokeWidth?: Float;
lineCap?: WithDefault<CGLineCap, "butt">;
lineJoin?: WithDefault<CGLineJoin, "miter">;
miterLimit?: Float;
lineDashPhase?: Float;
lineDashPattern?: LineDashPattern;
geodesic?: boolean;
onPress?: BubblingEventHandler<MapEvent>;
}
2. 执行本地CodeGen脚本工具
- 检查c++接口文件是否能生成
cd 项目根部目录
node ./node_modules/react-native/scripts/generate-artifacts.js --path . --outputPath ./ios
成功后c++接口文件在ios/build路径下
- 生成c++接口文件并导入到项目
修改或创建一个podspec
文件,具体参考官网 ios-create-the-podspec-file
主要是设置设置编译环境变量,c++版本,引入一些fabric组件需要依赖的一些库
准备好了podspec
文件就可以执行下面命令
cd ios目录下
USE_FABRIC=1 RCT_NEW_ARCH_ENABLED=1 pod install --verbose
遇到问题:
- ts接口规矩文件必须以NativeComponent结尾,不然CodeGen工具会过滤掉,导致没有c++ 接口文件的生成
3. 编写native code
具体实现参考官网 native-code
遇到的问题:
- 编译报错
Invalid operands to binary expression ('const facebook::react::std::vector<T>' and 'const facebook::react::std::vector<T>')
这个主要是对c++数组直接==比较导致的,目前通过oc方法比较数组里面的内容是否一致
-
Fabric组件不释放
Fabric组件创建后会被存入一个队列里面,被RN维护起来了;所以这里当Fabric组件unmount需要自己实现哪些视图和数据需要被释放关注这3个方法:
- (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index {
// 加载子视图
}
- (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index {
// 卸载子视图
}
- (void)prepareForRecycle {
// 重置属性状态数据
// 包括一些强引用子视图的释放
}
这3个方法能控制Fabric组件的子视图和数据释放
-
JS中报错在UIManager中未找到组件
requireNativeComponent: xxx was not found in the UIManager.
这个的原因是Fabric组件也依赖ViewManager,所以还需要单独建立一个ViewManager类,不然这个Fabric不会注册到全局组件数组中
这是RN加载组建到全局字典中的实现,最终都加载到_componentDataByName
_componentDataByName = [NSMutableDictionary new];
for (Class moduleClass in _bridge.moduleClasses) {
if ([moduleClass isSubclassOfClass:[RCTViewManager class]]) {
RCTComponentData *componentData = [[RCTComponentData alloc] initWithManagerClass:moduleClass bridge:_bridge eventDispatcher:_bridge.eventDispatcher];
_componentDataByName[componentData.name] = componentData;
}
}
-
Fabric组件在js更新属性时c++的updateProps:oldProps:没调用
这个问题也是ViewManager引起的,需要在ViewManager中把fabric的属性都再申明一遍