与现有应用集成
当您从头开始构建新的移动应用时,React Native 非常适用。但是,它也适用于向现有的原生应用添加单个视图或用户流程。只需几个步骤,您就可以添加基于 React Native 的新功能、屏幕、视图等。
具体步骤取决于您要定位的平台。
- Android (Java & Kotlin)
- iOS (Objective-C 和 Swift)
关键概念
将 React Native 组件集成到您的 Android 应用的关键在于
- 设置正确的目录结构。
- 安装必要的 NPM 依赖项。
- 将 React Native 添加到您的 Gradle 配置中。
- 为您的第一个 React Native 屏幕编写 TypeScript 代码。
- 使用 ReactActivity 将 React Native 与您的 Android 代码集成。
- 通过运行打包器并在实际操作中查看您的应用来测试您的集成。
使用社区模板
在您遵循本指南时,我们建议您参考 React Native 社区模板。该模板包含一个最小的 Android 应用,并将帮助您了解如何将 React Native 集成到现有的 Android 应用中。
先决条件
请遵循有关 设置开发环境 和使用 无框架的 React Native 的指南,以配置用于为 Android 构建 React Native 应用的开发环境。本指南还假设您熟悉 Android 开发的基础知识,例如创建 Activity 和编辑AndroidManifest.xml
文件。
1. 设置目录结构
为了确保顺畅的体验,请为您的集成 React Native 项目创建一个新文件夹,然后将您现有的 Android 项目移动到/android
子文件夹中。
2. 安装 NPM 依赖项
转到根目录并运行以下命令
curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.75-stable/template/package.json
这会将package.json
文件从社区模板复制到您的项目中。
接下来,通过运行以下命令安装 NPM 包
- npm
- Yarn
npm install
yarn install
安装过程创建了一个新的node_modules
文件夹。此文件夹存储构建项目所需的所有 JavaScript 依赖项。
将node_modules/
添加到您的.gitignore
文件(此处为 社区默认文件)。
3. 将 React Native 添加到您的应用
配置 Gradle
React Native 使用 React Native Gradle 插件来配置您的依赖项和项目设置。
首先,让我们通过添加这些行来编辑您的settings.gradle
文件(如 社区模板中建议的那样)
// Configures the React Native Gradle Settings plugin used for autolinking
pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") }
plugins { id("com.facebook.react.settings") }
extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() }
// If using .gradle.kts files:
// extensions.configure<com.facebook.react.ReactSettingsExtension> { autolinkLibrariesFromCommand() }
includeBuild("../node_modules/@react-native/gradle-plugin")
// Include your existing Gradle modules here.
// include(":app")
然后,您需要打开您的顶级build.gradle
并包含此行(如 社区模板中建议的那样)
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:7.3.1")
+ classpath("com.facebook.react:react-native-gradle-plugin")
}
}
这确保了 React Native Gradle 插件 (RNGP) 在您的项目中可用。最后,在您的应用程序的build.gradle
文件中添加这些行(这是一个不同的build.gradle
文件,通常位于您的app
文件夹中 - 您可以使用 社区模板文件作为参考)
apply plugin: "com.android.application"
+apply plugin: "com.facebook.react"
repositories {
mavenCentral()
}
dependencies {
// Other dependencies here
+ // Note: we intentionally don't specify the version number here as RNGP will take care of it.
+ // If you don't use the RNGP, you'll have to specify version manually.
+ implementation("com.facebook.react:react-android")
+ implementation("com.facebook.react:hermes-android")
}
+react {
+ // Needed to enable Autolinking - https://github.com/react-native-community/cli/blob/master/docs/autolinking.md
+ autolinkLibrariesWithApp()
+}
最后,打开您的应用程序gradle.properties
文件并添加以下行(此处为 社区模板文件作为参考)
+reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
+newArchEnabled=true
+hermesEnabled=true
配置清单
首先,确保您的AndroidManifest.xml
中具有 Internet 权限
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".MainApplication">
</application>
</manifest>
然后,您需要在调试AndroidManifest.xml
中启用 明文流量
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
+ android:usesCleartextTraffic="true"
+ tools:targetApi="28"
/>
</manifest>
像往常一样,此处为社区模板中的 AndroidManifest.xml 文件,用作参考:主文件 和 调试文件
这是必要的,因为您的应用程序将通过 HTTP 与本地打包器 [Metro][https://metrobundler.dev/] 通信。通过 HTTP。
确保仅将其添加到您的调试清单中。
4. 编写 TypeScript 代码
现在,我们将实际修改原生 Android 应用程序以集成 React Native。
我们将编写的第一个代码段是将集成到我们的应用程序中的新屏幕的实际 React Native 代码。
创建index.js
文件
首先,在 React Native 项目的根目录中创建一个空的index.js
文件。
index.js
是 React Native 应用程序的起点,并且始终是必需的。它可以是一个小的文件,import
其他作为 React Native 组件或应用程序一部分的文件,或者它可以包含所需的所有代码。
我们的 index.js 应该如下所示(此处为 社区模板文件作为参考)
import {AppRegistry} from 'react-native';
import App from './App';
AppRegistry.registerComponent('HelloWorld', () => App);
创建App.tsx
文件
让我们创建一个App.tsx
文件。这是一个 TypeScript 文件,可以包含 JSX 表达式。它包含我们将集成到 Android 应用程序中的根 React Native 组件(链接)
import React from 'react';
import {
SafeAreaView,
ScrollView,
StatusBar,
StyleSheet,
Text,
useColorScheme,
View,
} from 'react-native';
import {
Colors,
DebugInstructions,
Header,
ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';
function App(): React.JSX.Element {
const isDarkMode = useColorScheme() === 'dark';
const backgroundStyle = {
backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
};
return (
<SafeAreaView style={backgroundStyle}>
<StatusBar
barStyle={isDarkMode ? 'light-content' : 'dark-content'}
backgroundColor={backgroundStyle.backgroundColor}
/>
<ScrollView
contentInsetAdjustmentBehavior="automatic"
style={backgroundStyle}>
<Header />
<View
style={{
backgroundColor: isDarkMode
? Colors.black
: Colors.white,
padding: 24,
}}>
<Text style={styles.title}>Step One</Text>
<Text>
Edit <Text style={styles.bold}>App.tsx</Text> to
change this screen and see your edits.
</Text>
<Text style={styles.title}>See your changes</Text>
<ReloadInstructions />
<Text style={styles.title}>Debug</Text>
<DebugInstructions />
</View>
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
title: {
fontSize: 24,
fontWeight: '600',
},
bold: {
fontWeight: '700',
},
});
export default App;
此处为 社区模板文件作为参考
5. 与您的 Android 代码集成
现在我们需要添加一些原生代码,以便启动 React Native 运行时并告诉它渲染我们的 React 组件。
更新您的 Application 类
首先,我们需要更新您的Application
类,以便正确初始化 React Native,如下所示
- Java
- Kotlin
package <your-package-here>;
import android.app.Application;
+import com.facebook.react.PackageList;
+import com.facebook.react.ReactApplication;
+import com.facebook.react.ReactHost;
+import com.facebook.react.ReactNativeHost;
+import com.facebook.react.ReactPackage;
+import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
+import com.facebook.react.defaults.DefaultReactHost;
+import com.facebook.react.defaults.DefaultReactNativeHost;
+import com.facebook.soloader.SoLoader;
+import com.facebook.react.soloader.OpenSourceMergedSoMapping
+import java.util.List;
-class MainApplication extends Application {
+class MainApplication extends Application implements ReactApplication {
+ @Override
+ public ReactNativeHost getReactNativeHost() {
+ return new DefaultReactNativeHost(this) {
+ @Override
+ protected List<ReactPackage> getPackages() { return new PackageList(this).getPackages(); }
+ @Override
+ protected String getJSMainModuleName() { return "index"; }
+ @Override
+ public boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; }
+ @Override
+ protected boolean isNewArchEnabled() { return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; }
+ @Override
+ protected Boolean isHermesEnabled() { return BuildConfig.IS_HERMES_ENABLED; }
+ };
+ }
+ @Override
+ public ReactHost getReactHost() {
+ return DefaultReactHost.getDefaultReactHost(getApplicationContext(), getReactNativeHost());
+ }
@Override
public void onCreate() {
super.onCreate();
+ SoLoader.init(this, OpenSourceMergedSoMapping);
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
+ DefaultNewArchitectureEntryPoint.load();
+ }
}
}
// package <your-package-here>
import android.app.Application
+import com.facebook.react.PackageList
+import com.facebook.react.ReactApplication
+import com.facebook.react.ReactHost
+import com.facebook.react.ReactNativeHost
+import com.facebook.react.ReactPackage
+import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
+import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
+import com.facebook.react.defaults.DefaultReactNativeHost
+import com.facebook.soloader.SoLoader
-class MainApplication : Application() {
+class MainApplication : Application(), ReactApplication {
+ override val reactNativeHost: ReactNativeHost =
+ object : DefaultReactNativeHost(this) {
+ override fun getPackages(): List<ReactPackage> = PackageList(this).packages
+ override fun getJSMainModuleName(): String = "index"
+ override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
+ override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
+ override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
+ }
+ override val reactHost: ReactHost
+ get() = getDefaultReactHost(applicationContext, reactNativeHost)
override fun onCreate() {
super.onCreate()
+ SoLoader.init(this, false)
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
+ load()
+ }
}
}
像往常一样,此处为 MainApplication.kt 社区模板文件作为参考
创建一个ReactActivity
最后,我们需要创建一个新的Activity
,它将扩展ReactActivity
并承载 React Native 代码。此活动将负责启动 React Native 运行时并渲染 React 组件。
- Java
- Kotlin
// package <your-package-here>;
import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactActivityDelegate;
public class MyReactActivity extends ReactActivity {
@Override
protected String getMainComponentName() {
return "HelloWorld";
}
@Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new DefaultReactActivityDelegate(this, getMainComponentName(), DefaultNewArchitectureEntryPoint.getFabricEnabled());
}
}
// package <your-package-here>
import com.facebook.react.ReactActivity
import com.facebook.react.ReactActivityDelegate
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
import com.facebook.react.defaults.DefaultReactActivityDelegate
class MyReactActivity : ReactActivity() {
override fun getMainComponentName(): String = "HelloWorld"
override fun createReactActivityDelegate(): ReactActivityDelegate =
DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
}
像往常一样,此处为 MainActivity.kt 社区模板文件作为参考
每当您创建新的 Activity 时,都需要将其添加到您的AndroidManifest.xml
文件中。您还需要将MyReactActivity
的主题设置为Theme.AppCompat.Light.NoActionBar
(或任何非 ActionBar 主题),否则您的应用程序将在 React Native 屏幕顶部渲染 ActionBar
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".MainApplication">
+ <activity
+ android:name=".MyReactActivity"
+ android:label="@string/app_name"
+ android:theme="@style/Theme.AppCompat.Light.NoActionBar">
+ </activity>
</application>
</manifest>
现在您的活动已准备好运行一些 JavaScript 代码。
6. 测试您的集成
您已完成将 React Native 与您的应用程序集成的所有基本步骤。现在,我们将启动 Metro 打包器 以将您的 TypeScript 应用程序代码构建成一个包。Metro 的 HTTP 服务器从开发环境中的localhost
共享包到模拟器或设备。这允许 热重载。
首先,您需要在项目的根目录中创建metro.config.js
文件,如下所示
const {getDefaultConfig} = require('@react-native/metro-config');
module.exports = getDefaultConfig(__dirname);
您可以查看 metro.config.js 文件,将其作为社区模板文件参考。
一旦您拥有配置文件,就可以运行打包器。在项目的根目录中运行以下命令
- npm
- Yarn
npm start
yarn start
现在像往常一样构建并运行您的 Android 应用。
到达应用中的 React 供电的 Activity 后,它应该加载来自开发服务器的 JavaScript 代码并显示
在 Android Studio 中创建发布版本
您也可以使用 Android Studio 创建发布版本!这与创建您以前存在的原生 Android 应用的发布版本一样快。
React Native Gradle 插件将负责将 JS 代码捆绑到您的 APK/App Bundle 中。
如果您没有使用 Android Studio,您可以使用以下命令创建发布版本:
cd android
# For a Release APK
./gradlew :app:assembleRelease
# For a Release AAB
./gradlew :app:bundleRelease
现在怎么办?
此时,您可以像往常一样继续开发您的应用。请参阅我们的 调试 和 部署 文档,以了解有关使用 React Native 的更多信息。
关键概念
将 React Native 组件集成到 iOS 应用程序的关键在于
- 设置正确的目录结构。
- 安装必要的 NPM 依赖项。
- 将 React Native 添加到您的 Podfile 配置中。
- 为您的第一个 React Native 屏幕编写 TypeScript 代码。
- 使用
RCTRootView
将 React Native 与您的 iOS 代码集成。 - 通过运行打包器并在实际操作中查看您的应用来测试您的集成。
使用社区模板
在您遵循本指南时,我们建议您参考 React Native 社区模板。该模板包含一个最小的 iOS 应用程序,将帮助您了解如何将 React Native 集成到现有的 iOS 应用程序中。
先决条件
请遵循有关 设置开发环境 和使用 无框架的 React Native 的指南来配置您的开发环境,以便为 iOS 构建 React Native 应用。本指南还假设您熟悉 iOS 开发的基础知识,例如创建 UIViewController
和编辑 Podfile
文件。
1. 设置目录结构
为了确保顺畅的体验,请为您的集成 React Native 项目创建一个新文件夹,然后将现有 iOS 项目移动到 /ios
子文件夹中。
2. 安装 NPM 依赖项
转到根目录并运行以下命令
curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.76-stable/template/package.json
这将从社区模板将 package.json
文件 复制到您的项目中。
接下来,通过运行以下命令安装 NPM 包
- npm
- Yarn
npm install
yarn install
安装过程创建了一个新的node_modules
文件夹。此文件夹存储构建项目所需的所有 JavaScript 依赖项。
将 node_modules/
添加到您的 .gitignore
文件中(此处为 社区默认文件)。
3. 安装开发工具
Xcode 命令行工具
安装命令行工具。在 Xcode 菜单中选择设置...(或首选项...)。转到“位置”面板,并通过在“命令行工具”下拉列表中选择最新版本来安装工具。
CocoaPods
CocoaPods 是用于 iOS 和 macOS 开发的包管理工具。我们使用它将实际的 React Native 框架代码本地添加到您的当前项目中。
我们建议使用 Homebrew 安装 CocoaPods。
brew install cocoapods
4. 将 React Native 添加到您的应用
配置 CocoaPods
要配置 CocoaPods,我们需要两个文件
- 一个Gemfile,定义了我们需要哪些 Ruby 依赖项。
- 一个Podfile,定义了如何正确安装我们的依赖项。
对于Gemfile,转到项目的根目录并运行以下命令
curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.76-stable/template/Gemfile
这将从模板下载 Gemfile。类似地,对于Podfile,转到项目的 ios
文件夹并运行
curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.76-stable/template/ios/Podfile
请使用社区模板作为参考点,以了解 Gemfile 和 Podfile。
现在,我们需要运行几个额外的命令来安装 Ruby gem 和 Pod。导航到 ios
文件夹并运行以下命令
bundle install
bundle exec pod install
第一个命令将安装 Ruby 依赖项,第二个命令将实际将 React Native 代码集成到您的应用程序中,以便您的 iOS 文件可以导入 React Native 头文件。
5. 编写 TypeScript 代码
现在我们将实际修改原生 iOS 应用程序以集成 React Native。
我们将编写的第一个代码段是将集成到我们的应用程序中的新屏幕的实际 React Native 代码。
创建index.js
文件
首先,在 React Native 项目的根目录中创建一个空的index.js
文件。
index.js
是 React Native 应用程序的起点,并且始终是必需的。它可以是一个小的文件,import
其他作为 React Native 组件或应用程序一部分的文件,或者它可以包含所需的所有代码。
我们的 index.js
应如下所示(此处为 社区模板文件作为参考)
import {AppRegistry} from 'react-native';
import App from './App';
AppRegistry.registerComponent('HelloWorld', () => App);
创建App.tsx
文件
让我们创建一个 App.tsx
文件。这是一个 TypeScript 文件,可以包含 JSX 表达式。它包含我们将集成到 iOS 应用程序中的根 React Native 组件(链接)
import React from 'react';
import {
SafeAreaView,
ScrollView,
StatusBar,
StyleSheet,
Text,
useColorScheme,
View,
} from 'react-native';
import {
Colors,
DebugInstructions,
Header,
ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';
function App(): React.JSX.Element {
const isDarkMode = useColorScheme() === 'dark';
const backgroundStyle = {
backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
};
return (
<SafeAreaView style={backgroundStyle}>
<StatusBar
barStyle={isDarkMode ? 'light-content' : 'dark-content'}
backgroundColor={backgroundStyle.backgroundColor}
/>
<ScrollView
contentInsetAdjustmentBehavior="automatic"
style={backgroundStyle}>
<Header />
<View
style={{
backgroundColor: isDarkMode
? Colors.black
: Colors.white,
padding: 24,
}}>
<Text style={styles.title}>Step One</Text>
<Text>
Edit <Text style={styles.bold}>App.tsx</Text> to
change this screen and see your edits.
</Text>
<Text style={styles.title}>See your changes</Text>
<ReloadInstructions />
<Text style={styles.title}>Debug</Text>
<DebugInstructions />
</View>
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
title: {
fontSize: 24,
fontWeight: '600',
},
bold: {
fontWeight: '700',
},
});
export default App;
此处为 社区模板文件作为参考
5. 与您的 iOS 代码集成
现在我们需要添加一些原生代码,以便启动 React Native 运行时并告诉它渲染我们的 React 组件。
要求
React Native 应该与 AppDelegate
一起使用。以下部分假设您的 AppDelegate
如下所示
- ObjectiveC
- Swift
#import "AppDelegate.h"
#import "ViewController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate {
UIWindow *window;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
window = [UIWindow new];
window.rootViewController = [ViewController new];
[window makeKeyAndVisible];
return YES;
}
@end
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow()
window?.rootViewController = ViewController()
window?.makeKeyAndVisible()
return true
}
}
更新 AppDelegate
类
首先,我们需要扩展 AppDelegate
以继承 React Native 提供的类之一:RCTAppDelegate
。
- ObjectiveC
- Swift
为此,我们必须修改 AppDelegate.h
文件和 AppDelegate.m
文件
- 打开
AppDelegate.h
文件并按如下方式修改它(请参阅官方模板的 AppDelegate.h 作为参考)
#import <UIKit/UIKit.h>
+#import <React-RCTAppDelegate/RCTAppDelegate.h>
-@interface AppDelegate : UIResponder <UIApplicationDelegate>
+@interface AppDelegate : RCTAppDelegate
@end
- 打开
AppDelegate.mm
文件并按如下方式修改它(请参阅官方模板的 AppDelegate.mm 作为参考
#import "AppDelegate.h"
#import "ViewController.h"
+#import <React/RCTBundleURLProvider.h>
@interface AppDelegate ()
@end
@implementation AppDelegate {
UIWindow *window;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ self.automaticallyLoadReactNativeWindow = NO;
+ return [super application:application didFinishLaunchingWithOptions:launchOptions];
window = [UIWindow new];
window.rootViewController = [ViewController new];
[window makeKeyAndVisible];
return YES;
}
+- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
+{
+ return [self bundleURL];
+}
+- (NSURL *)bundleURL
+{
+#if DEBUG
+ return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
+#else
+ return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
+#endif
+}
@end
让我们看一下上面的代码
- 我们正在继承
RCTAppDelegate
,并且我们正在调用RCTAppDelegate
的application:didFinishLaunchingWithOptions
。这将所有 React Native 初始化过程委托给基类。 - 我们通过将
automaticallyLoadReactNativeWindow
设置为NO
来自定义RCTAppDelegate
。此步骤指示 React Native 应用程序正在处理UIWindow
,React Native 不必担心这一点。 sourceURLForBridge:
和bundleURL
方法用于应用程序通知 React Native 在哪里可以找到需要呈现的 JS 包。sourceURLForBridge:
来自旧架构,您可以看到它将决策推迟到新架构所需的bundleURL
方法。
为此,我们必须修改 AppDelegate.swift
- 打开
AppDelegate.swift
文件并按如下方式修改它(请参阅官方模板的 AppDelegate.swift 作为参考)
import UIKit
+import React_RCTAppDelegate
+import React_RCTAppDelegate
@main
-class AppDelegate: UIResponder, UIApplicationDelegate {
+class AppDelegate: RCTAppDelegate {
- var window: UIWindow?
- func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+ override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
+ self.automaticallyLoadReactNativeWindow = false
+ super.application(application, didFinishLaunchingWithOptions: launchOptions)
window = UIWindow()
- window?.rootViewController = ViewController()
- window?.makeKeyAndVisible()
+ window.rootViewController = ViewController()
+ window.makeKeyAndVisible()
return true
}
+ override func sourceURL(for bridge: RCTBridge) -> URL? {
+ self.bundleURL()
+ }
+ override func bundleURL() -> URL? {
+#if DEBUG
+ RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
+#else
+ Bundle.main.url(forResource: "main", withExtension: "jsbundle")
+#endif
+ }
}
让我们看一下上面的代码
- 我们正在继承
RCTAppDelegate
,并且我们正在调用RCTAppDelegate
的application(_:didFinishLaunchingWithOptions:)
。这将所有 React Native 初始化过程委托给基类。 - 我们通过将
automaticallyLoadReactNativeWindow
设置为false
来自定义RCTAppDelegate
。此步骤指示 React Native 应用程序正在处理UIWindow
,React Native 不必担心这一点。 sourceURLForBridge(for:)
和bundleURL()
方法用于应用程序通知 React Native 在哪里可以找到需要呈现的 JS 包。sourceURLForBridge(for:)
来自旧架构,您可以看到它将决策推迟到新架构所需的bundleURL()
方法。
在 rootViewController 中呈现 React Native 视图
最后,我们可以呈现我们的 React Native 视图。为此,我们需要一个新的视图控制器,它可以在其中承载一个视图,我们可以在其中加载 JS 内容。
- 从 Xcode 中,让我们创建一个新的
UIViewController
(让我们将其命名为ReactViewController
)。 - 让初始
ViewController
呈现ReactViewController
。有几种方法可以做到这一点,具体取决于您的应用。在本例中,我们假设您有一个以模态方式呈现 React Native 的按钮。
- ObjectiveC
- Swift
#import "ViewController.h"
+#import "ReactViewController.h"
@interface ViewController ()
@end
- @implementation ViewController
+@implementation ViewController {
+ ReactViewController *reactViewController;
+}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = UIColor.systemBackgroundColor;
+ UIButton *button = [UIButton new];
+ [button setTitle:@"Open React Native" forState:UIControlStateNormal];
+ [button setTitleColor:UIColor.systemBlueColor forState:UIControlStateNormal];
+ [button setTitleColor:UIColor.blueColor forState:UIControlStateHighlighted];
+ [button addTarget:self action:@selector(presentReactNative) forControlEvents:UIControlEventTouchUpInside];
+ [self.view addSubview:button];
+ button.translatesAutoresizingMaskIntoConstraints = NO;
+ [NSLayoutConstraint activateConstraints:@[
+ [button.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
+ [button.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
+ [button.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor],
+ [button.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor],
+ ]];
}
+- (void)presentReactNative
+{
+ if (reactViewController == NULL) {
+ reactViewController = [ReactViewController new];
+ }
+ [self presentViewController:reactViewController animated:YES completion:nil];
+}
@end
import UIKit
class ViewController: UIViewController {
+ var reactViewController: ReactViewController?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.view.backgroundColor = .systemBackground
+ let button = UIButton()
+ button.setTitle("Open React Native", for: .normal)
+ button.setTitleColor(.systemBlue, for: .normal)
+ button.setTitleColor(.blue, for: .highlighted)
+ button.addAction(UIAction { [weak self] _ in
+ if reactViewController == nil {
+ reactViewController = ReactViewController()
+ }
+ self?.present(reactViewController, animated: true)
+ }, for: .touchUpInside)
+ self.view.addSubview(button)
+
+ button.translatesAutoresizingMaskIntoConstraints = false
+ NSLayoutConstraint.activate([
+ button.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
+ button.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
+ button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
+ button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
+ ])
}
}
- 按如下方式更新
ReactViewController
代码
- ObjectiveC
- Swift
#import "ReactViewController.h"
+#import <React-RCTAppDelegate/RCTRootViewFactory.h>
+#import <React-RCTAppDelegate/RCTAppDelegate.h>
@interface ReactViewController ()
@end
@implementation ReactViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
+ RCTRootViewFactory *factory = ((RCTAppDelegate *)RCTSharedApplication().delegate).rootViewFactory;
+ self.view = [factory viewWithModuleName:@"HelloWorld"];
}
@end
import UIKit
+import React_RCTAppDelegate
class ReactViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
+ let factory = (RCTSharedApplication()?.delegate as? RCTAppDelegate)?.rootViewFactory
+ self.view = factory?.view(withModuleName: "HelloWorld")
}
}
- 确保禁用沙盒脚本。为此,在 Xcode 中,单击您的应用,然后单击构建设置。筛选脚本并设置
User Script Sandboxing
为NO
。此步骤需要在 React Native 附带的 Hermes 引擎 的调试版本和发布版本之间正确切换。
;
6. 测试您的集成
您已完成将 React Native 与您的应用程序集成的所有基本步骤。现在,我们将启动 Metro 打包器 以将您的 TypeScript 应用程序代码构建成一个包。Metro 的 HTTP 服务器从开发环境中的localhost
共享包到模拟器或设备。这允许 热重载。
首先,您需要在项目的根目录中创建metro.config.js
文件,如下所示
const {getDefaultConfig} = require('@react-native/metro-config');
module.exports = getDefaultConfig(__dirname);
您可以查看 metro.config.js 文件,将其作为社区模板文件参考。
一旦您拥有配置文件,就可以运行打包器。在项目的根目录中运行以下命令
- npm
- Yarn
npm start
yarn start
现在像往常一样构建并运行您的 iOS 应用。
到达应用中的 React 供电的 Activity 后,它应该加载来自开发服务器的 JavaScript 代码并显示
在 Xcode 中创建发布版本
您也可以使用 Xcode 创建发布版本!唯一的额外步骤是添加一个在构建应用时执行的脚本,以将您的 JS 和图像打包到 iOS 应用程序中。
- 在 Xcode 中,选择您的应用程序
- 单击
Build Phases
- 单击左上角的
+
并选择New Run Script Phase
- 单击
Run Script
行并将脚本重命名为Bundle React Native code and images
- 在文本框中粘贴以下脚本
set -e
WITH_ENVIRONMENT="$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh"
REACT_NATIVE_XCODE="$REACT_NATIVE_PATH/scripts/react-native-xcode.sh"
/bin/sh -c "$WITH_ENVIRONMENT $REACT_NATIVE_XCODE"
- 将脚本拖放到名为
[CP] Embed Pods Frameworks
的脚本之前。
现在,如果您构建应用以供发布,它将按预期工作。
现在怎么办?
此时,您可以像往常一样继续开发您的应用。请参阅我们的 调试 和 部署 文档,以了解有关使用 React Native 的更多信息。