进阶 reactnative.dev 2026-10-11 06:04:21 · 33 阅读

第39章 React Native Fabric 原生组件开发:iOS 篇

版本:0.77Fabric Native Components:iOS接下来我们要编写一些 iOS 平台代码来渲染 web 视图。需要完成的步骤有: 运行 Codegen。 编写 RCTWebView 代码 在应用中注册 RCTWebView 1. 运行 Codegen​ 你可以手动运行 Codegen,但更简单的做法是借助你用来演示组件的应用自动完成。 cd ios
bundle install
bundle exec pod install
重要的是,你会在日志输出中看到 Codegen 的信息,之后我们会在 Xcode 里基于它构建 WebView 原生组件。 warning注意不要把生成的代码提交到仓库里。生成的代码与特定版本的 React Native 绑定,建议通过 npm peerDependencies 来限制与 React Native 版本的兼容性。 3. 编写 RCTWebView​ 我们需要用 Xcode 完成 5 个步骤来准备 iOS 项目: 打开 CocoaPods 生成的 Xcode Workspace: cd ios
open Demo.xcworkspace
右键点击 app,选择 New Group,将新分组命名为 WebView。 在 WebView 分组中,选择 New→File from Template。 使用 Objective-C File 模板,命名为 RCTWebView 重复第 4 步,创建一个名为 RCTWebView.h 的头文件。 将 RCTWebView.m 重命名为 RCTWebView.mm,使其成为 Objective-C++ 文件。 Demo/iosPodfile
...
Demo
├── AppDelegate.swift
...
├── RCTWebView.h
└── RCTWebView.mm
创建好头文件和实现文件后,就可以开始编写具体实现了。 下面是 RCTWebView.h 文件的代码,用于声明组件接口。 Demo/RCTWebView/RCTWebView.h#import
#import

NS_ASSUME_NONNULL_BEGIN

@interface RCTWebView : RCTViewComponentView

// 你想从视图中访问的原生方法在这里声明

@end

NS_ASSUME_NONNULL_END
这个类定义了 RCTWebView,它继承自 RCTViewComponentView。这是所有原生组件的基类,由 React Native 提供。 实现文件(RCTWebView.mm)的代码如下: Demo/RCTWebView/RCTWebView.mm#import "RCTWebView.h"

#import
#import
#import
#import
#import

using namespace facebook::react;

@interface RCTWebView ()
@end

@implementation RCTWebView {
NSURL * _sourceURL;
WKWebView * _webView;
}

-(instancetype)init
{
if(self = [super init]) {
_webView = [WKWebView new];
_webView.navigationDelegate = self;
[self addSubview:_webView];
}
return self;
}

- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
{
const auto &oldViewProps = *std::static_pointer_cast(_props);
const auto &newViewProps = *std::static_pointer_cast(props);

// Handle your props here
if (oldViewProps.sourceURL != newViewProps.sourceURL) {
NSString *urlString = [NSString stringWithCString:newViewProps.sourceURL.c_str() encoding:NSUTF8StringEncoding];
_sourceURL = [NSURL URLWithString:urlString];
if ([self urlIsValid:newViewProps.sourceURL]) {
[_webView loadRequest:[NSURLRequest requestWithURL:_sourceURL]];
}
}

[super updateProps:props oldProps:oldProps];
}

-(void)layoutSubviews
{
[super layoutSubviews];
_webView.frame = self.bounds;

}

#pragma mark - WKNavigationDelegate

-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
CustomWebViewEventEmitter::OnScriptLoaded result = CustomWebViewEventEmitter::OnScriptLoaded{CustomWebViewEventEmitter::OnScriptLoadedResult::Success};
self.eventEmitter.onScriptLoaded(result);
}

- (BOOL)urlIsValid:(std::string)propString
{
if (propString.length() > 0 && !_sourceURL) {
CustomWebViewEventEmitter::OnScriptLoaded result = CustomWebViewEventEmitter::OnScriptLoaded{CustomWebViewEventEmitter::OnScriptLoadedResult::Error};

self.eventEmitter.onScriptLoaded(result);
return NO;
}
return YES;
}

// Event emitter convenience method
- (const CustomWebViewEventEmitter &)eventEmitter
{
return static_cast(*_eventEmitter);
}

+ (ComponentDescriptorProvider)componentDescriptorProvider
{
return concreteComponentDescriptorProvider();
}

@end
这段代码使用 Objective-C++ 编写,包含以下关键细节: @interface 实现了两个协议: * RCTCustomWebViewViewProtocol,由 Codegen 生成; * WKNavigationDelegate,由 WebKit 框架提供,用于处理 web 视图的导航事件; * init 方法:实例化 WKWebView,将其添加为子视图,并设置 navigationDelegate; * updateProps 方法:当组件的 props 发生变化时,由 React Native 调用; * layoutSubviews 方法:描述自定义视图的布局方式; * webView:didFinishNavigation: 方法:处理 WKWebView 完成页面加载后的操作; * urlIsValid:(std::string)propString 方法:检查作为 prop 传入的 URL 是否有效; * eventEmitter 方法:用于获取强类型 eventEmitter 实例的工具方法; * componentDescriptorProvider:返回由 Codegen 生成的 ComponentDescriptor。 添加 WebKit 框架 注意,这一步仅在创建 Web 视图时需要。iOS 上的 Web 组件需要链接 Apple 提供的 WebKit 框架。如果你的组件不需要访问 web 相关功能,可以跳过此步。 web 视图需要使用 Apple 通过 Xcode 及设备自带框架提供的一项功能:WebKit。 你可以在原生代码中看到 RCTWebView.mm 里添加的 `#import ` 这一行。 要在应用中链接 WebKit 框架,请按以下步骤操作: 1. 在 Xcode 中,点击你的项目 2. 选择 app target 3. 选择 General 标签页 4. 向下滚动直到找到 "Frameworks, Libraries, and Embedded Contents" 部分,然后点击 + 按钮 1. 在搜索栏中过滤 WebKit 2. 选择 WebKit 框架 3. 点击 Add

评论 (0)