与现有应用集成
当你从头开始开发新的移动应用时,React Native 非常有用。但是,它也适用于向现有原生应用添加单个视图或用户流。只需几个步骤,你就可以添加新的基于 React Native 的功能、屏幕、视图等。
¥React Native is great when you are starting a new mobile app from scratch. However, it also works well for adding a single view or user flow to existing native applications. With a few steps, you can add new React Native based features, screens, views, etc.
具体步骤会有所不同,具体取决于你的目标平台。
¥The specific steps are different depending on what platform you're targeting.
- Android (Kotlin)
- Android (Java)
- iOS (Objective-C)
- iOS (Swift)
关键概念
¥Key Concepts
将 React Native 组件集成到 Android 应用中的关键是:
¥The keys to integrating React Native components into your Android application are to:
-
设置 React Native 依赖和目录结构。
¥Set up React Native dependencies and directory structure.
-
使用 JavaScript 开发 React Native 组件。
¥Develop your React Native components in JavaScript.
-
将
ReactRootView
添加到你的 Android 应用中。该视图将用作 React Native 组件的容器。¥Add a
ReactRootView
to your Android app. This view will serve as the container for your React Native component. -
启动 React Native 服务器并运行你的原生应用。
¥Start the React Native server and run your native application.
-
验证应用的 React Native 方面是否按预期工作。
¥Verify that the React Native aspect of your application works as expected.
先决条件
¥Prerequisites
按照 设置你的开发环境 上的指南并使用 无需框架的 React Native 配置你的开发环境以构建适用于 Android 的 React Native 应用。
¥Follow the guide on setting up your development environment and using React Native without a framework to configure your development environment for building React Native apps for Android.
1. 设置目录结构
¥ Set up directory structure
为了确保流畅的体验,请为集成的 React Native 项目创建一个新文件夹,然后将现有的 Android 项目复制到 /android
子文件夹。
¥To ensure a smooth experience, create a new folder for your integrated React Native project, then copy your existing Android project to an /android
subfolder.
2. 安装 JavaScript 依赖
¥ Install JavaScript dependencies
转到项目的根目录并创建一个新的 package.json
文件,其中包含以下内容:
¥Go to the root directory for your project and create a new package.json
file with the following contents:
{
"name": "MyReactNativeApp",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "yarn react-native start"
}
}
接下来,安装 react
和 react-native
软件包。打开终端或命令提示符,然后导航到包含 package.json
文件的目录并运行:
¥Next, install the react
and react-native
packages. Open a terminal or command prompt, then navigate to the directory with your package.json
file and run:
- npm
- Yarn
npm install react-native
yarn add react-native
这将打印一条类似于以下内容的消息(在安装命令输出中向上滚动以查看它):
¥This will print a message similar to the following (scroll up in the installation command output to see it):
警告“
react-native@0.70.5
”未满足对等依赖“react@18.1.0
Ӵwarning "
react-native@0.70.5
" has unmet peer dependency "react@18.1.0
"
没关系,这意味着我们还需要安装 React:
¥This is OK, it means we also need to install React:
- npm
- Yarn
npm install react@version_printed_above
yarn add react@version_printed_above
安装过程创建了一个新的 /node_modules
文件夹。此文件夹存储构建项目所需的所有 JavaScript 依赖。
¥Installation process has created a new /node_modules
folder. This folder stores all the JavaScript dependencies required to build your project.
将 node_modules/
添加到 .gitignore
文件中。
¥Add node_modules/
to your .gitignore
file.
将 React Native 添加到你的应用
¥Adding React Native to your app
配置 Gradle
¥Configuring Gradle
React Native 使用 React Native Gradle 插件来配置依赖和项目设置。
¥React Native uses the React Native Gradle Plugin to configure your dependencies and project setup.
首先,让我们通过添加以下行来编辑 settings.gradle
文件:
¥First, let's edit your settings.gradle
file by adding this line:
includeBuild('../node_modules/@react-native/gradle-plugin')
然后你需要打开顶层 build.gradle
并包含以下行:
¥Then you need to open your top level build.gradle
and include this line:
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 插件在你的项目中可用。最后,将这些行添加到应用的 build.gradle
文件中(它是应用文件夹中的不同 build.gradle
文件):
¥This makes sure the React Native Gradle Plugin is available inside your project.
Finally, add those lines inside your app's build.gradle
file (it's a different build.gradle
file inside your app folder):
apply plugin: "com.android.application"
+apply plugin: "com.facebook.react"
repositories {
mavenCentral()
}
dependencies {
// Other dependencies here
+ implementation "com.facebook.react:react-android"
+ implementation "com.facebook.react:hermes-android"
}
这些依赖在 mavenCentral()
上可用,因此请确保在 repositories{}
块中定义了它。
¥Those depedencies are available on mavenCentral()
so make sure you have it defined in your repositories{}
block.
我们故意不指定这些 implementation
依赖的版本,因为 React Native Gradle 插件会处理它。如果你不使用 React Native Gradle 插件,则必须手动指定版本。
¥We intentionally don't specify the version for those implementation
dependencies as the React Native Gradle Plugin will take care of it. If you don't use the React Native Gradle Plugin, you'll have to specify version manually.
启用原生模块自动链接
¥Enable native modules autolinking
为了发挥 autolinking 的威力,我们必须在几个地方应用它。首先将以下条目添加到 settings.gradle
:
¥To use the power of autolinking, we have to apply it a few places. First add the following entry to settings.gradle
:
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
接下来在 app/build.gradle
的最底部添加以下条目:
¥Next add the following entry at the very bottom of the app/build.gradle
:
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
配置权限
¥Configuring permissions
接下来,确保你的 AndroidManifest.xml
具有 Internet 权限:
¥Next, make sure you have the Internet permission in your AndroidManifest.xml
:
<uses-permission android:name="android.permission.INTERNET" />
如果你需要访问 DevSettingsActivity
,请添加到你的 AndroidManifest.xml
:
¥If you need to access to the DevSettingsActivity
add to your AndroidManifest.xml
:
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
这仅在从开发服务器重新加载 JavaScript 时在开发模式下使用,因此如果需要,你可以在发布版本中删除它。
¥This is only used in dev mode when reloading JavaScript from the development server, so you can strip this in release builds if you need to.
明文流量(API 级别 28+)
¥Cleartext Traffic (API level 28+)
从 Android 9(API 级别 28)开始,默认禁用明文流量;这会阻止你的应用连接到 Metro 打包器。以下更改允许调试版本中的明文流量。
¥Starting with Android 9 (API level 28), cleartext traffic is disabled by default; this prevents your application from connecting to the Metro bundler. The changes below allow cleartext traffic in debug builds.
1. 将 usesCleartextTraffic
选项应用于你的调试 AndroidManifest.xml
¥ Apply the usesCleartextTraffic
option to your Debug AndroidManifest.xml
<!-- ... -->
<application
android:usesCleartextTraffic="true" tools:targetApi="28" >
<!-- ... -->
</application>
<!-- ... -->
对于发布版本来说这不是必需的。
¥This is not required for Release builds.
了解有关网络安全配置和明文流量策略 看到这个链接 的更多信息。
¥To learn more about Network Security Config and the cleartext traffic policy see this link.
代码集成
¥Code integration
现在我们将实际修改原生 Android 应用以集成 React Native。
¥Now we will actually modify the native Android application to integrate React Native.
React Native 组件
¥The React Native component
我们将编写的第一段代码是将新的 "高分" 屏幕的实际 React Native 代码集成到我们的应用中。
¥The first bit of code we will write is the actual React Native code for the new "High Score" screen that will be integrated into our application.
1. 创建 index.js
文件
¥ Create a index.js
file
首先,在 React Native 项目的根目录中创建一个空的 index.js
文件。
¥First, create an empty index.js
file in the root of your React Native project.
index.js
是 React Native 应用的起点,并且始终是必需的。它可以是一个小文件,或者是 React Native 组件或应用中的其他文件,也可以包含它所需的所有代码。在我们的例子中,我们将把所有内容都放在 index.js
中。
¥index.js
is the starting point for React Native applications, and it is always required. It can be a small file that require
s other file that are part of your React Native component or application, or it can contain all the code that is needed for it. In our case, we will put everything in index.js
.
2. 添加你的 React Native 代码
¥ Add your React Native code
在 index.js
中,创建你的组件。在我们的示例中,我们将在样式化的 <View>
中添加 <Text>
组件:
¥In your index.js
, create your component. In our sample here, we will add a <Text>
component within a styled <View>
:
import React from 'react';
import {AppRegistry, StyleSheet, Text, View} from 'react-native';
const HelloWorld = () => {
return (
<View style={styles.container}>
<Text style={styles.hello}>Hello, World</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
hello: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
});
AppRegistry.registerComponent(
'MyReactNativeApp',
() => HelloWorld,
);
3. 配置开发错误覆盖的权限
¥ Configure permissions for development error overlay
如果你的应用面向 Android API level 23
或更高版本,请确保你拥有为开发版本启用的权限 android.permission.SYSTEM_ALERT_WINDOW
。你可以通过 Settings.canDrawOverlays(this)
进行检查。这在开发版本中是必需的,因为 React Native 开发错误必须显示在所有其他窗口之上。由于 API 级别 23(Android M)中引入了新的权限系统,需要用户批准。这可以通过将以下代码添加到你的 Activity 的 onCreate()
方法中来实现。
¥If your app is targeting the Android API level 23
or greater, make sure you have the permission android.permission.SYSTEM_ALERT_WINDOW
enabled for the development build. You can check this with Settings.canDrawOverlays(this)
. This is required in dev builds because React Native development errors must be displayed above all the other windows. Due to the new permissions system introduced in the API level 23 (Android M), the user needs to approve it. This can be achieved by adding the following code to your Activity's in onCreate()
method.
companion object {
const val OVERLAY_PERMISSION_REQ_CODE = 1 // Choose any value
}
...
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if(!Settings.canDrawOverlays(this)) {
val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package: $packageName"))
startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
}
}
最后,必须重写 onActivityResult()
方法(如下面的代码所示)来处理权限接受或拒绝的情况,以获得一致的用户体验。此外,为了集成使用 startActivityForResult
的原生模块,我们需要将结果传递给 ReactInstanceManager
实例的 onActivityResult
方法。
¥Finally, the onActivityResult()
method (as shown in the code below) has to be overridden to handle the permission Accepted or Denied cases for consistent UX. Also, for integrating Native Modules which use startActivityForResult
, we need to pass the result to the onActivityResult
method of our ReactInstanceManager
instance.
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
// SYSTEM_ALERT_WINDOW permission not granted
}
}
}
reactInstanceManager?.onActivityResult(this, requestCode, resultCode, data)
}
魔术:ReactRootView
¥The Magic: ReactRootView
让我们添加一些原生代码来启动 React Native 运行时并告诉它渲染我们的 JS 组件。为此,我们将创建一个 Activity
,它创建一个 ReactRootView
,在其中启动一个 React 应用并将其设置为主要内容视图。
¥Let's add some native code in order to start the React Native runtime and tell it to render our JS component. To do this, we're going to create an Activity
that creates a ReactRootView
, starts a React application inside it and sets it as the main content view.
如果你的目标是 Android 版本 <5,请使用
com.android.support:appcompat
包中的AppCompatActivity
类而不是Activity
。¥If you are targeting Android version <5, use the
AppCompatActivity
class from thecom.android.support:appcompat
package instead ofActivity
.
class MyReactActivity : Activity(), DefaultHardwareBackBtnHandler {
private lateinit var reactRootView: ReactRootView
private lateinit var reactInstanceManager: ReactInstanceManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
SoLoader.init(this, false)
reactRootView = ReactRootView(this)
val packages: List<ReactPackage> = PackageList(application).packages
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(MyReactNativePackage())
// Remember to include them in `settings.gradle` and `app/build.gradle` too.
reactInstanceManager = ReactInstanceManager.builder()
.setApplication(application)
.setCurrentActivity(this)
.setBundleAssetName("index.android.bundle")
.setJSMainModulePath("index")
.addPackages(packages)
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build()
// The string here (e.g. "MyReactNativeApp") has to match
// the string in AppRegistry.registerComponent() in index.js
reactRootView?.startReactApplication(reactInstanceManager, "MyReactNativeApp", null)
setContentView(reactRootView)
}
override fun invokeDefaultOnBackPressed() {
super.onBackPressed()
}
}
如果你使用的是 React Native 入门套件,请将 "HelloWorld" 字符串替换为 index.js 文件中的字符串(它是
AppRegistry.registerComponent()
方法的第一个参数)。¥If you are using a starter kit for React Native, replace the "HelloWorld" string with the one in your index.js file (it’s the first argument to the
AppRegistry.registerComponent()
method).
执行“与 Gradle 同步项目文件”操作。
¥Perform a “Sync Project files with Gradle” operation.
如果你使用的是 Android Studio,请使用 Alt + Enter
在 MyReactActivity 类中添加所有缺少的导入。请小心使用你的包中的 BuildConfig
,而不是 facebook
包中的包。
¥If you are using Android Studio, use Alt + Enter
to add all missing imports in your MyReactActivity class. Be careful to use your package’s BuildConfig
and not the one from the facebook
package.
我们需要将 MyReactActivity
的主题设置为 Theme.AppCompat.Light.NoActionBar
,因为一些 React Native UI 组件依赖于该主题。
¥We need set the theme of MyReactActivity
to Theme.AppCompat.Light.NoActionBar
because some React Native UI components rely on this theme.
<activity
android:name=".MyReactActivity"
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
</activity>
ReactInstanceManager
可以由多个活动和/或片段共享。你将想要制作自己的ReactFragment
或ReactActivity
,并拥有一个可容纳ReactInstanceManager
的单括号。当你需要ReactInstanceManager
(例如,将ReactInstanceManager
连接到这些活动或片段的生命周期)时,请使用单例提供的ReactInstanceManager
。¥A
ReactInstanceManager
can be shared by multiple activities and/or fragments. You will want to make your ownReactFragment
orReactActivity
and have a singleton holder that holds aReactInstanceManager
. When you need theReactInstanceManager
(e.g., to hook up theReactInstanceManager
to the lifecycle of those Activities or Fragments) use the one provided by the singleton.
接下来,我们需要将一些 Activity 生命周期回调传递给 ReactInstanceManager
和 ReactRootView
:
¥Next, we need to pass some activity lifecycle callbacks to the ReactInstanceManager
and ReactRootView
:
override fun onPause() {
super.onPause()
reactInstanceManager.onHostPause(this)
}
override fun onResume() {
super.onResume()
reactInstanceManager.onHostResume(this, this)
}
override fun onDestroy() {
super.onDestroy()
reactInstanceManager.onHostDestroy(this)
reactRootView.unmountReactApplication()
}
我们还需要将返回按钮事件传递给 React Native:
¥We also need to pass back button events to React Native:
override fun onBackPressed() {
reactInstanceManager.onBackPressed()
super.onBackPressed()
}
这允许 JavaScript 控制用户按下硬件后退按钮时发生的情况(例如实现导航)。当 JavaScript 不处理后退按钮按下时,你的 invokeDefaultOnBackPressed
方法将被调用。默认情况下,这将完成你的 Activity
。
¥This allows JavaScript to control what happens when the user presses the hardware back button (e.g. to implement navigation). When JavaScript doesn't handle the back button press, your invokeDefaultOnBackPressed
method will be called. By default this finishes your Activity
.
最后,我们需要连接开发菜单。默认情况下,这是通过(愤怒)摇动设备来激活的,但这在模拟器中不是很有用。因此,我们让它在你按下硬件菜单按钮时显示(如果你使用的是 Android Studio 模拟器,请使用 Ctrl + M):
¥Finally, we need to hook up the dev menu. By default, this is activated by (rage) shaking the device, but this is not very useful in emulators. So we make it show when you press the hardware menu button (use Ctrl + M if you're using Android Studio emulator):
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
if (keyCode == KeyEvent.KEYCODE_MENU && reactInstanceManager != null) {
reactInstanceManager.showDevOptionsDialog()
return true
}
return super.onKeyUp(keyCode, event)
}
现在你的 Activity 已准备好运行一些 JavaScript 代码。
¥Now your activity is ready to run some JavaScript code.
测试你的集成
¥Test your integration
你现在已经完成了将 React Native 与当前应用集成的所有基本步骤。现在我们将启动 Metro 打包器 来构建 index.bundle
包,并在本地主机上运行服务器来为其提供服务。
¥You have now done all the basic steps to integrate React Native with your current application. Now we will start the Metro bundler to build the index.bundle
package and the server running on localhost to serve it.
1. 运行打包器
¥ Run the packager
要运行你的应用,你需要首先启动开发服务器。为此,请在 React Native 项目的根目录中运行以下命令:
¥To run your app, you need to first start the development server. To do this, run the following command in the root directory of your React Native project:
- npm
- Yarn
npm start
yarn start
2. 运行应用
¥ Run the app
现在正常构建并运行你的 Android 应用。
¥Now build and run your Android app as normal.
一旦你到达应用内由 React 支持的活动,它应该从开发服务器加载 JavaScript 代码并显示:
¥Once you reach your React-powered activity inside the app, it should load the JavaScript code from the development server and display:
在 Android Studio 中创建发布版本
¥Creating a release build in Android Studio
你也可以使用 Android Studio 创建你的发布版本!它就像为你之前存在的原生 Android 应用创建发布版本一样快。
¥You can use Android Studio to create your release builds too! It’s as quick as creating release builds of your previously-existing native Android app.
如果你如上所述使用 React Native Gradle 插件,则从 Android Studio 运行应用时一切都应该正常。
¥If you use the React Native Gradle Plugin as described above, everything should work when running app from Android Studio.
如果你不使用 React Native Gradle 插件,则在每次发布构建之前都必须执行一个额外步骤。你需要执行以下命令来创建 React Native 打包包,该打包包将包含在你的原生 Android 应用中:
¥If you're not using the React Native Gradle Plugin, there’s one additional step which you’ll have to do before every release build. You need to execute the following to create a React Native bundle, which will be included with your native Android app:
$ npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/com/your-company-name/app-package-name/src/main/assets/index.android.bundle --assets-dest android/com/your-company-name/app-package-name/src/main/res/
不要忘记用正确的路径替换路径,并创建资源文件夹(如果不存在)。
¥Don’t forget to replace the paths with correct ones and create the assets folder if it doesn’t exist.
现在,像往常一样从 Android Studio 中创建原生应用的发布版本,你应该可以开始了!
¥Now, create a release build of your native app from within Android Studio as usual and you should be good to go!
怎么办?
¥Now what?
此时,你可以像往常一样继续开发你的应用。请参阅我们的 debugging 和 deployment 文档,了解有关使用 React Native 的更多信息。
¥At this point you can continue developing your app as usual. Refer to our debugging and deployment docs to learn more about working with React Native.
关键概念
¥Key Concepts
将 React Native 组件集成到 Android 应用中的关键是:
¥The keys to integrating React Native components into your Android application are to:
-
设置 React Native 依赖和目录结构。
¥Set up React Native dependencies and directory structure.
-
使用 JavaScript 开发 React Native 组件。
¥Develop your React Native components in JavaScript.
-
将
ReactRootView
添加到你的 Android 应用中。该视图将用作 React Native 组件的容器。¥Add a
ReactRootView
to your Android app. This view will serve as the container for your React Native component. -
启动 React Native 服务器并运行你的原生应用。
¥Start the React Native server and run your native application.
-
验证应用的 React Native 方面是否按预期工作。
¥Verify that the React Native aspect of your application works as expected.
先决条件
¥Prerequisites
按照 设置你的开发环境 上的指南配置你的开发环境以构建适用于 Android 的 React Native 应用。
¥Follow the guide on setting up your development environment to configure your development environment for building React Native apps for Android.
1. 设置目录结构
¥ Set up directory structure
为了确保流畅的体验,请为集成的 React Native 项目创建一个新文件夹,然后将现有的 Android 项目复制到 /android
子文件夹。
¥To ensure a smooth experience, create a new folder for your integrated React Native project, then copy your existing Android project to an /android
subfolder.
2. 安装 JavaScript 依赖
¥ Install JavaScript dependencies
转到项目的根目录并创建一个新的 package.json
文件,其中包含以下内容:
¥Go to the root directory for your project and create a new package.json
file with the following contents:
{
"name": "MyReactNativeApp",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "react-native start"
}
}
接下来,安装 react
和 react-native
软件包。打开终端或命令提示符,然后导航到包含 package.json
文件的目录并运行:
¥Next, install the react
and react-native
packages. Open a terminal or command prompt, then navigate to the directory with your package.json
file and run:
- npm
- Yarn
npm install react-native
yarn add react-native
这将打印一条类似于以下内容的消息(在安装命令输出中向上滚动以查看它):
¥This will print a message similar to the following (scroll up in the installation command output to see it):
警告“
react-native@0.70.5
”未满足对等依赖“react@18.1.0
Ӵwarning "
react-native@0.70.5
" has unmet peer dependency "react@18.1.0
"
没关系,这意味着我们还需要安装 React:
¥This is OK, it means we also need to install React:
- npm
- Yarn
npm install react@version_printed_above
yarn add react@version_printed_above
安装过程创建了一个新的 /node_modules
文件夹。此文件夹存储构建项目所需的所有 JavaScript 依赖。
¥Installation process has created a new /node_modules
folder. This folder stores all the JavaScript dependencies required to build your project.
将 node_modules/
添加到 .gitignore
文件中。
¥Add node_modules/
to your .gitignore
file.
将 React Native 添加到你的应用
¥Adding React Native to your app
配置 Gradle
¥Configuring Gradle
React Native 使用 React Native Gradle 插件来配置依赖和项目设置。
¥React Native uses the React Native Gradle Plugin to configure your dependencies and project setup.
首先,让我们通过添加以下行来编辑 settings.gradle
文件:
¥First, let's edit your settings.gradle
file by adding this line:
includeBuild('../node_modules/@react-native/gradle-plugin')
然后你需要打开顶层 build.gradle
并包含以下行:
¥Then you need to open your top level build.gradle
and include this line:
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 插件在你的项目中可用。最后,将这些行添加到应用的 build.gradle
文件中(它是应用文件夹中的不同 build.gradle
文件):
¥This makes sure the React Native Gradle Plugin is available inside your project.
Finally, add those lines inside your app's build.gradle
file (it's a different build.gradle
file inside your app folder):
apply plugin: "com.android.application"
+apply plugin: "com.facebook.react"
repositories {
mavenCentral()
}
dependencies {
// Other dependencies here
+ implementation "com.facebook.react:react-android"
+ implementation "com.facebook.react:hermes-android"
}
这些依赖在 mavenCentral()
上可用,因此请确保在 repositories{}
块中定义了它。
¥Those depedencies are available on mavenCentral()
so make sure you have it defined in your repositories{}
block.
我们故意不指定这些 implementation
依赖的版本,因为 React Native Gradle 插件会处理它。如果你不使用 React Native Gradle 插件,则必须手动指定版本。
¥We intentionally don't specify the version for those implementation
dependencies as the React Native Gradle Plugin will take care of it. If you don't use the React Native Gradle Plugin, you'll have to specify version manually.
启用原生模块自动链接
¥Enable native modules autolinking
为了发挥 autolinking 的威力,我们必须在几个地方应用它。首先将以下条目添加到 settings.gradle
:
¥To use the power of autolinking, we have to apply it a few places. First add the following entry to settings.gradle
:
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
接下来在 app/build.gradle
的最底部添加以下条目:
¥Next add the following entry at the very bottom of the app/build.gradle
:
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
配置权限
¥Configuring permissions
接下来,确保你的 AndroidManifest.xml
具有 Internet 权限:
¥Next, make sure you have the Internet permission in your AndroidManifest.xml
:
<uses-permission android:name="android.permission.INTERNET" />
如果你需要访问 DevSettingsActivity
,请添加到你的 AndroidManifest.xml
:
¥If you need to access to the DevSettingsActivity
add to your AndroidManifest.xml
:
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
这仅在从开发服务器重新加载 JavaScript 时在开发模式下使用,因此如果需要,你可以在发布版本中删除它。
¥This is only used in dev mode when reloading JavaScript from the development server, so you can strip this in release builds if you need to.
明文流量(API 级别 28+)
¥Cleartext Traffic (API level 28+)
从 Android 9(API 级别 28)开始,默认禁用明文流量;这会阻止你的应用连接到 Metro 打包器。以下更改允许调试版本中的明文流量。
¥Starting with Android 9 (API level 28), cleartext traffic is disabled by default; this prevents your application from connecting to the Metro bundler. The changes below allow cleartext traffic in debug builds.
1. 将 usesCleartextTraffic
选项应用于你的调试 AndroidManifest.xml
¥ Apply the usesCleartextTraffic
option to your Debug AndroidManifest.xml
<!-- ... -->
<application
android:usesCleartextTraffic="true" tools:targetApi="28" >
<!-- ... -->
</application>
<!-- ... -->
对于发布版本来说这不是必需的。
¥This is not required for Release builds.
了解有关网络安全配置和明文流量策略 看到这个链接 的更多信息。
¥To learn more about Network Security Config and the cleartext traffic policy see this link.
代码集成
¥Code integration
现在我们将实际修改原生 Android 应用以集成 React Native。
¥Now we will actually modify the native Android application to integrate React Native.
React Native 组件
¥The React Native component
我们将编写的第一段代码是将新的 "高分" 屏幕的实际 React Native 代码集成到我们的应用中。
¥The first bit of code we will write is the actual React Native code for the new "High Score" screen that will be integrated into our application.
1. 创建 index.js
文件
¥ Create a index.js
file
首先,在 React Native 项目的根目录中创建一个空的 index.js
文件。
¥First, create an empty index.js
file in the root of your React Native project.
index.js
是 React Native 应用的起点,并且始终是必需的。它可以是一个小文件,或者是 React Native 组件或应用中的其他文件,也可以包含它所需的所有代码。在我们的例子中,我们将把所有内容都放在 index.js
中。
¥index.js
is the starting point for React Native applications, and it is always required. It can be a small file that require
s other file that are part of your React Native component or application, or it can contain all the code that is needed for it. In our case, we will put everything in index.js
.
2. 添加你的 React Native 代码
¥ Add your React Native code
在 index.js
中,创建你的组件。在我们的示例中,我们将在样式化的 <View>
中添加 <Text>
组件:
¥In your index.js
, create your component. In our sample here, we will add a <Text>
component within a styled <View>
:
import React from 'react';
import {AppRegistry, StyleSheet, Text, View} from 'react-native';
const HelloWorld = () => {
return (
<View style={styles.container}>
<Text style={styles.hello}>Hello, World</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
hello: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
});
AppRegistry.registerComponent(
'MyReactNativeApp',
() => HelloWorld,
);
3. 配置开发错误覆盖的权限
¥ Configure permissions for development error overlay
如果你的应用面向 Android API level 23
或更高版本,请确保你拥有为开发版本启用的权限 android.permission.SYSTEM_ALERT_WINDOW
。你可以通过 Settings.canDrawOverlays(this);
进行检查。这在开发版本中是必需的,因为 React Native 开发错误必须显示在所有其他窗口之上。由于 API 级别 23(Android M)中引入了新的权限系统,需要用户批准。这可以通过将以下代码添加到你的 Activity 的 onCreate()
方法中来实现。
¥If your app is targeting the Android API level 23
or greater, make sure you have the permission android.permission.SYSTEM_ALERT_WINDOW
enabled for the development build. You can check this with Settings.canDrawOverlays(this);
. This is required in dev builds because React Native development errors must be displayed above all the other windows. Due to the new permissions system introduced in the API level 23 (Android M), the user needs to approve it. This can be achieved by adding the following code to your Activity's in onCreate()
method.
private final int OVERLAY_PERMISSION_REQ_CODE = 1; // Choose any value
...
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
}
}
最后,必须重写 onActivityResult()
方法(如下面的代码所示)来处理权限接受或拒绝的情况,以获得一致的用户体验。此外,为了集成使用 startActivityForResult
的原生模块,我们需要将结果传递给 ReactInstanceManager
实例的 onActivityResult
方法。
¥Finally, the onActivityResult()
method (as shown in the code below) has to be overridden to handle the permission Accepted or Denied cases for consistent UX. Also, for integrating Native Modules which use startActivityForResult
, we need to pass the result to the onActivityResult
method of our ReactInstanceManager
instance.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
// SYSTEM_ALERT_WINDOW permission not granted
}
}
}
mReactInstanceManager.onActivityResult( this, requestCode, resultCode, data );
}
魔术:ReactRootView
¥The Magic: ReactRootView
让我们添加一些原生代码来启动 React Native 运行时并告诉它渲染我们的 JS 组件。为此,我们将创建一个 Activity
,它创建一个 ReactRootView
,在其中启动一个 React 应用并将其设置为主要内容视图。
¥Let's add some native code in order to start the React Native runtime and tell it to render our JS component. To do this, we're going to create an Activity
that creates a ReactRootView
, starts a React application inside it and sets it as the main content view.
如果你的目标是 Android 版本 <5,请使用
com.android.support:appcompat
包中的AppCompatActivity
类而不是Activity
。¥If you are targeting Android version <5, use the
AppCompatActivity
class from thecom.android.support:appcompat
package instead ofActivity
.
public class MyReactActivity extends Activity implements DefaultHardwareBackBtnHandler {
private ReactRootView mReactRootView;
private ReactInstanceManager mReactInstanceManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SoLoader.init(this, false);
mReactRootView = new ReactRootView(this);
List<ReactPackage> packages = new PackageList(getApplication()).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
// Remember to include them in `settings.gradle` and `app/build.gradle` too.
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setCurrentActivity(this)
.setBundleAssetName("index.android.bundle")
.setJSMainModulePath("index")
.addPackages(packages)
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
// The string here (e.g. "MyReactNativeApp") has to match
// the string in AppRegistry.registerComponent() in index.js
mReactRootView.startReactApplication(mReactInstanceManager, "MyReactNativeApp", null);
setContentView(mReactRootView);
}
@Override
public void invokeDefaultOnBackPressed() {
super.onBackPressed();
}
}
如果你使用的是 React Native 入门套件,请将 "HelloWorld" 字符串替换为 index.js 文件中的字符串(它是
AppRegistry.registerComponent()
方法的第一个参数)。¥If you are using a starter kit for React Native, replace the "HelloWorld" string with the one in your index.js file (it’s the first argument to the
AppRegistry.registerComponent()
method).
执行“与 Gradle 同步项目文件”操作。
¥Perform a “Sync Project files with Gradle” operation.
如果你使用的是 Android Studio,请使用 Alt + Enter
在 MyReactActivity 类中添加所有缺少的导入。请小心使用你的包中的 BuildConfig
,而不是 facebook
包中的包。
¥If you are using Android Studio, use Alt + Enter
to add all missing imports in your MyReactActivity class. Be careful to use your package’s BuildConfig
and not the one from the facebook
package.
我们需要将 MyReactActivity
的主题设置为 Theme.AppCompat.Light.NoActionBar
,因为一些 React Native UI 组件依赖于该主题。
¥We need set the theme of MyReactActivity
to Theme.AppCompat.Light.NoActionBar
because some React Native UI components rely on this theme.
<activity
android:name=".MyReactActivity"
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
</activity>
ReactInstanceManager
可以由多个活动和/或片段共享。你将想要制作自己的ReactFragment
或ReactActivity
,并拥有一个可容纳ReactInstanceManager
的单括号。当你需要ReactInstanceManager
(例如,将ReactInstanceManager
连接到这些活动或片段的生命周期)时,请使用单例提供的ReactInstanceManager
。¥A
ReactInstanceManager
can be shared by multiple activities and/or fragments. You will want to make your ownReactFragment
orReactActivity
and have a singleton holder that holds aReactInstanceManager
. When you need theReactInstanceManager
(e.g., to hook up theReactInstanceManager
to the lifecycle of those Activities or Fragments) use the one provided by the singleton.
接下来,我们需要将一些 Activity 生命周期回调传递给 ReactInstanceManager
和 ReactRootView
:
¥Next, we need to pass some activity lifecycle callbacks to the ReactInstanceManager
and ReactRootView
:
@Override
protected void onPause() {
super.onPause();
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostPause(this);
}
}
@Override
protected void onResume() {
super.onResume();
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostResume(this, this);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mReactInstanceManager != null) {
mReactInstanceManager.onHostDestroy(this);
}
if (mReactRootView != null) {
mReactRootView.unmountReactApplication();
}
}
我们还需要将返回按钮事件传递给 React Native:
¥We also need to pass back button events to React Native:
@Override
public void onBackPressed() {
if (mReactInstanceManager != null) {
mReactInstanceManager.onBackPressed();
} else {
super.onBackPressed();
}
}
这允许 JavaScript 控制用户按下硬件后退按钮时发生的情况(例如实现导航)。当 JavaScript 不处理后退按钮按下时,你的 invokeDefaultOnBackPressed
方法将被调用。默认情况下,这将完成你的 Activity
。
¥This allows JavaScript to control what happens when the user presses the hardware back button (e.g. to implement navigation). When JavaScript doesn't handle the back button press, your invokeDefaultOnBackPressed
method will be called. By default this finishes your Activity
.
最后,我们需要连接开发菜单。默认情况下,这是通过(愤怒)摇动设备来激活的,但这在模拟器中不是很有用。因此,我们让它在你按下硬件菜单按钮时显示(如果你使用的是 Android Studio 模拟器,请使用 Ctrl + M):
¥Finally, we need to hook up the dev menu. By default, this is activated by (rage) shaking the device, but this is not very useful in emulators. So we make it show when you press the hardware menu button (use Ctrl + M if you're using Android Studio emulator):
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
mReactInstanceManager.showDevOptionsDialog();
return true;
}
return super.onKeyUp(keyCode, event);
}
现在你的 Activity 已准备好运行一些 JavaScript 代码。
¥Now your activity is ready to run some JavaScript code.
测试你的集成
¥Test your integration
你现在已经完成了将 React Native 与当前应用集成的所有基本步骤。现在我们将启动 Metro 打包器 来构建 index.bundle
包,并在本地主机上运行服务器来为其提供服务。
¥You have now done all the basic steps to integrate React Native with your current application. Now we will start the Metro bundler to build the index.bundle
package and the server running on localhost to serve it.
1. 运行打包器
¥ Run the packager
要运行你的应用,你需要首先启动开发服务器。为此,请在 React Native 项目的根目录中运行以下命令:
¥To run your app, you need to first start the development server. To do this, run the following command in the root directory of your React Native project:
- npm
- Yarn
npm start
yarn start
2. 运行应用
¥ Run the app
现在正常构建并运行你的 Android 应用。
¥Now build and run your Android app as normal.
一旦你到达应用内由 React 支持的活动,它应该从开发服务器加载 JavaScript 代码并显示:
¥Once you reach your React-powered activity inside the app, it should load the JavaScript code from the development server and display:
在 Android Studio 中创建发布版本
¥Creating a release build in Android Studio
你也可以使用 Android Studio 创建你的发布版本!它就像为你之前存在的原生 Android 应用创建发布版本一样快。
¥You can use Android Studio to create your release builds too! It’s as quick as creating release builds of your previously-existing native Android app.
如果你如上所述使用 React Native Gradle 插件,则从 Android Studio 运行应用时一切都应该正常。
¥If you use the React Native Gradle Plugin as described above, everything should work when running app from Android Studio.
如果你不使用 React Native Gradle 插件,则在每次发布构建之前都必须执行一个额外步骤。你需要执行以下命令来创建 React Native 打包包,该打包包将包含在你的原生 Android 应用中:
¥If you're not using the React Native Gradle Plugin, there’s one additional step which you’ll have to do before every release build. You need to execute the following to create a React Native bundle, which will be included with your native Android app:
$ npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/com/your-company-name/app-package-name/src/main/assets/index.android.bundle --assets-dest android/com/your-company-name/app-package-name/src/main/res/
不要忘记用正确的路径替换路径,并创建资源文件夹(如果不存在)。
¥Don’t forget to replace the paths with correct ones and create the assets folder if it doesn’t exist.
现在,像往常一样从 Android Studio 中创建原生应用的发布版本,你应该可以开始了!
¥Now, create a release build of your native app from within Android Studio as usual and you should be good to go!
怎么办?
¥Now what?
此时,你可以像往常一样继续开发你的应用。请参阅我们的 debugging 和 deployment 文档,了解有关使用 React Native 的更多信息。
¥At this point you can continue developing your app as usual. Refer to our debugging and deployment docs to learn more about working with React Native.
关键概念
¥Key Concepts
将 React Native 组件集成到 iOS 应用中的关键是:
¥The keys to integrating React Native components into your iOS application are to:
-
设置 React Native 依赖和目录结构。
¥Set up React Native dependencies and directory structure.
-
了解你将在应用中使用哪些 React Native 组件。
¥Understand what React Native components you will use in your app.
-
使用 CocoaPods 将这些组件添加为依赖。
¥Add these components as dependencies using CocoaPods.
-
使用 JavaScript 开发 React Native 组件。
¥Develop your React Native components in JavaScript.
-
将
RCTRootView
添加到你的 iOS 应用中。该视图将用作 React Native 组件的容器。¥Add a
RCTRootView
to your iOS app. This view will serve as the container for your React Native component. -
启动 React Native 服务器并运行你的原生应用。
¥Start the React Native server and run your native application.
-
验证应用的 React Native 方面是否按预期工作。
¥Verify that the React Native aspect of your application works as expected.
先决条件
¥Prerequisites
按照 设置你的开发环境 上的指南并使用 无需框架的 React Native 配置你的开发环境以构建适用于 iOS 的 React Native 应用。
¥Follow the guide on setting up your development environment and using React Native without a framework to configure your development environment for building React Native apps for iOS.
1. 设置目录结构
¥ Set up directory structure
为了确保流畅的体验,请为集成的 React Native 项目创建一个新文件夹,然后将现有的 iOS 项目复制到 /ios
子文件夹。
¥To ensure a smooth experience, create a new folder for your integrated React Native project, then copy your existing iOS project to a /ios
subfolder.
2. 安装 JavaScript 依赖
¥ Install JavaScript dependencies
转到项目的根目录并创建一个新的 package.json
文件,其中包含以下内容:
¥Go to the root directory for your project and create a new package.json
file with the following contents:
{
"name": "MyReactNativeApp",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "yarn react-native start"
}
}
接下来,确保你有 安装了 Yarn 包管理器。
¥Next, make sure you have installed the yarn package manager.
安装 react
和 react-native
软件包。打开终端或命令提示符,然后导航到包含 package.json
文件的目录并运行:
¥Install the react
and react-native
packages. Open a terminal or command prompt, then navigate to the directory with your package.json
file and run:
- npm
- Yarn
npm install react-native
yarn add react-native
这将打印一条类似于以下内容的消息(在安装命令输出中向上滚动以查看它):
¥This will print a message similar to the following (scroll up in the installation command output to see it):
警告“
react-native@0.52.2
”未满足对等依赖“react@16.2.0
”。¥warning "
react-native@0.52.2
" has unmet peer dependency "react@16.2.0
".
没关系,这意味着我们还需要安装 React:
¥This is OK, it means we also need to install React:
- npm
- Yarn
npm install react@version_printed_above
yarn add react@version_printed_above
安装过程创建了一个新的 /node_modules
文件夹。此文件夹存储构建项目所需的所有 JavaScript 依赖。
¥Installation process has created a new /node_modules
folder. This folder stores all the JavaScript dependencies required to build your project.
将 node_modules/
添加到 .gitignore
文件中。
¥Add node_modules/
to your .gitignore
file.
3. 安装 CocoaPods
¥ Install CocoaPods
CocoaPods 是一款用于 iOS 和 macOS 开发的包管理工具。我们使用它来将实际的 React Native 框架代码本地添加到你当前的项目中。
¥CocoaPods is a package management tool for iOS and macOS development. We use it to add the actual React Native framework code locally into your current project.
我们建议使用 Homebrew 安装 CocoaPods。
¥We recommend installing CocoaPods using Homebrew.
brew install cocoapods
从技术上讲,不使用 CocoaPods 是可能的,但这需要手动添加库和链接器,这会使这个过程变得过于复杂。
¥It is technically possible not to use CocoaPods, but that would require manual library and linker additions that would overly complicate this process.
将 React Native 添加到你的应用
¥Adding React Native to your app
假设 用于集成的应用 是 2048 游戏。这是没有 React Native 时原生应用的主菜单的样子。
¥Assume the app for integration is a 2048 game. Here is what the main menu of the native application looks like without React Native.
Xcode 命令行工具
¥Command Line Tools for Xcode
安装命令行工具。选择设置...(或首选项...)在 Xcode 菜单中。转到“位置”面板并通过在“命令行工具”下拉列表中选择最新版本来安装工具。
¥Install the Command Line Tools. Choose Settings... (or Preferences...) in the Xcode menu. Go to the Locations panel and install the tools by selecting the most recent version in the Command Line Tools dropdown.
配置 CocoaPods 依赖
¥Configuring CocoaPods dependencies
在将 React Native 集成到应用中之前,你需要决定要集成 React Native 框架的哪些部分。我们将使用 CocoaPods 来指定你的应用将依赖于这些 "subspecs" 中的哪一个。
¥Before you integrate React Native into your application, you will want to decide what parts of the React Native framework you would like to integrate. We will use CocoaPods to specify which of these "subspecs" your app will depend on.
支持的 subspec
列表可在 /node_modules/react-native/React.podspec
中找到。它们通常按功能命名。例如,你通常总是想要 Core
subspec
。这将为你提供 AppRegistry
、StyleSheet
、View
和其他核心 React Native 库。如果你想添加 React Native Text
库(例如,对于 <Text>
元素),那么你将需要 RCTText
subspec
。如果你想要 Image
库(例如,对于 <Image>
元素),那么你将需要 RCTImage
subspec
。
¥The list of supported subspec
s is available in /node_modules/react-native/React.podspec
. They are generally named by functionality. For example, you will generally always want the Core
subspec
. That will get you the AppRegistry
, StyleSheet
, View
and other core React Native libraries. If you want to add the React Native Text
library (e.g., for <Text>
elements), then you will need the RCTText
subspec
. If you want the Image
library (e.g., for <Image>
elements), then you will need the RCTImage
subspec
.
你可以在 Podfile
文件中指定你的应用将依赖哪个 subspec
。创建 Podfile
最简单的方法是在项目的 /ios
子文件夹中运行 CocoaPods init
命令:
¥You can specify which subspec
s your app will depend on in a Podfile
file. The easiest way to create a Podfile
is by running the CocoaPods init
command in the /ios
subfolder of your project:
pod init
Podfile
将包含一个样板设置,你可以根据集成目的对其进行调整。
¥The Podfile
will contain a boilerplate setup that you will tweak for your integration purposes.
Podfile
版本根据你的react-native
版本而变化。请参阅 https://react-native-community.github.io/upgrade-helper/ 了解你应使用的Podfile
的具体版本。¥The
Podfile
version changes depending on your version ofreact-native
. Refer to https://react-native-community.github.io/upgrade-helper/ for the specific version ofPodfile
you should be using.
最终,你的 Podfile
应该类似于以下内容:
¥Ultimately, your Podfile
should look something similar to this:
# The target name is most likely the name of your project.
target 'NumberTileGame' do
# Your 'node_modules' directory is probably in the root of your project,
# but if not, adjust the `:path` accordingly
pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
pod 'React', :path => '../node_modules/react-native/'
pod 'React-Core', :path => '../node_modules/react-native/'
pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'
pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
pod 'ReactCommon/callinvoker', :path => "../node_modules/react-native/ReactCommon"
pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
end
创建 Podfile
后,你就可以安装 React Native pod。
¥After you have created your Podfile
, you are ready to install the React Native pod.
$ pod install
你应该看到如下输出:
¥You should see output such as:
Analyzing dependencies
Fetching podspec for `React` from `../node_modules/react-native`
Downloading dependencies
Installing React (0.62.0)
Generating Pods project
Integrating client project
Sending stats
Pod installation complete! There are 3 dependencies from the Podfile and 1 total pod installed.
如果此操作失败并出现提及
xcrun
的错误,请确保在 Xcode 的“设置”中...(或首选项...)> 分配命令行工具的位置。¥If this fails with errors mentioning
xcrun
, make sure that in Xcode in Settings... (or Preferences...) > Locations the Command Line Tools are assigned.
代码集成
¥Code integration
现在我们将实际修改原生 iOS 应用以集成 React Native。对于我们的 2048 示例应用,我们将在 React Native 中添加 "高分" 屏幕。
¥Now we will actually modify the native iOS application to integrate React Native. For our 2048 sample app, we will add a "High Score" screen in React Native.
React Native 组件
¥The React Native component
我们将编写的第一段代码是将新的 "高分" 屏幕的实际 React Native 代码集成到我们的应用中。
¥The first bit of code we will write is the actual React Native code for the new "High Score" screen that will be integrated into our application.
1. 创建 index.js
文件
¥ Create a index.js
file
首先,在 React Native 项目的根目录中创建一个空的 index.js
文件。
¥First, create an empty index.js
file in the root of your React Native project.
index.js
是 React Native 应用的起点,并且始终是必需的。它可以是一个小文件,或者是 React Native 组件或应用中的其他文件,也可以包含它所需的所有代码。在我们的例子中,我们将把所有内容都放在 index.js
中。
¥index.js
is the starting point for React Native applications, and it is always required. It can be a small file that require
s other file that are part of your React Native component or application, or it can contain all the code that is needed for it. In our case, we will put everything in index.js
.
2. 添加你的 React Native 代码
¥ Add your React Native code
在 index.js
中,创建你的组件。在我们的示例中,我们将在样式化的 <View>
中添加 <Text>
组件
¥In your index.js
, create your component. In our sample here, we will add a <Text>
component within a styled <View>
import React from 'react';
import {AppRegistry, StyleSheet, Text, View} from 'react-native';
const RNHighScores = ({scores}) => {
const contents = scores.map(score => (
<Text key={score.name}>
{score.name}:{score.value}
{'\n'}
</Text>
));
return (
<View style={styles.container}>
<Text style={styles.highScoresTitle}>
2048 High Scores!
</Text>
<Text style={styles.scores}>{contents}</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FFFFFF',
},
highScoresTitle: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
scores: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
// Module name
AppRegistry.registerComponent('RNHighScores', () => RNHighScores);
RNHighScores
是你的模块的名称,当你从 iOS 应用中向 React Native 添加视图时将使用该名称。¥
RNHighScores
is the name of your module that will be used when you add a view to React Native from within your iOS application.
魔术:RCTRootView
¥The Magic: RCTRootView
现在你的 React Native 组件是通过 index.js
创建的,你需要将该组件添加到新的或现有的 ViewController
中。最简单的路径是有选择地创建组件的事件路径,然后将该组件添加到现有的 ViewController
。
¥Now that your React Native component is created via index.js
, you need to add that component to a new or existing ViewController
. The easiest path to take is to optionally create an event path to your component and then add that component to an existing ViewController
.
我们将把我们的 React Native 组件与 ViewController
中的一个新的原生视图联系起来,该视图实际上包含它,称为 RCTRootView
。
¥We will tie our React Native component with a new native view in the ViewController
that will actually contain it called RCTRootView
.
1. 创建事件路径
¥ Create an Event Path
你可以在主游戏菜单上添加新链接以转到 "高分" React Native 页面。
¥You can add a new link on the main game menu to go to the "High Score" React Native page.
2. 事件处理程序
¥ Event Handler
我们现在将从菜单链接添加一个事件处理程序。一个方法将被添加到你的应用的主 ViewController
中。这就是 RCTRootView
发挥作用的地方。
¥We will now add an event handler from the menu link. A method will be added to the main ViewController
of your application. This is where RCTRootView
comes into play.
当你构建 React Native 应用时,你可以使用 Metro 打包器 创建将由 React Native 服务器提供服务的 index.bundle
。index.bundle
内部将是我们的 RNHighScore
模块。因此,我们需要将 RCTRootView
指向 index.bundle
资源的位置(通过 NSURL
)并将其绑定到模块。
¥When you build a React Native application, you use the Metro bundler to create an index.bundle
that will be served by the React Native server. Inside index.bundle
will be our RNHighScore
module. So, we need to point our RCTRootView
to the location of the index.bundle
resource (via NSURL
) and tie it to the module.
出于调试目的,我们将记录事件处理程序被调用。然后,我们将创建一个字符串,其中包含 index.bundle
中存在的 React Native 代码的位置。最后,我们将创建主 RCTRootView
。请注意,在为 React Native 组件编写代码时,我们如何提供 RNHighScores
作为我们创建的 above 的 moduleName
。
¥We will, for debugging purposes, log that the event handler was invoked. Then, we will create a string with the location of our React Native code that exists inside the index.bundle
. Finally, we will create the main RCTRootView
. Notice how we provide RNHighScores
as the moduleName
that we created above when writing the code for our React Native component.
首先是 import
和 RCTRootView
标头。
¥First import
the RCTRootView
header.
#import <React/RCTRootView.h>
initialProperties
在这里用于说明目的,因此我们有一些高分屏幕的数据。在我们的 React Native 组件中,我们将使用this.props
来访问该数据。¥The
initialProperties
are here for illustration purposes so we have some data for our high score screen. In our React Native component, we will usethis.props
to get access to that data.
- (IBAction)highScoreButtonPressed:(id)sender {
NSLog(@"High Score Button Pressed");
NSURL *jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.bundle?platform=ios"];
RCTRootView *rootView =
[[RCTRootView alloc] initWithBundleURL: jsCodeLocation
moduleName: @"RNHighScores"
initialProperties:
@{
@"scores" : @[
@{
@"name" : @"Alex",
@"value": @"42"
},
@{
@"name" : @"Joel",
@"value": @"10"
}
]
}
launchOptions: nil];
UIViewController *vc = [[UIViewController alloc] init];
vc.view = rootView;
[self presentViewController:vc animated:YES completion:nil];
}
请注意,
RCTRootView initWithURL
启动了一个新的 JSC VM。为了节省资源并简化原生应用不同部分中 RN 视图之间的通信,你可以拥有由 React Native 提供支持的多个视图,这些视图与单个 JS 运行时关联。为此,请使用RCTBridge initWithBundleURL
创建桥,然后使用RCTRootView initWithBridge
,而不是使用[RCTRootView alloc] initWithURL
。¥Note that
RCTRootView initWithURL
starts up a new JSC VM. To save resources and simplify the communication between RN views in different parts of your native app, you can have multiple views powered by React Native that are associated with a single JS runtime. To do that, instead of using[RCTRootView alloc] initWithURL
, useRCTBridge initWithBundleURL
to create a bridge and then useRCTRootView initWithBridge
.
将应用转移到生产环境时,
NSURL
可以通过[[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
之类的方式指向磁盘上的预打包文件。你可以使用node_modules/react-native/scripts/
中的react-native-xcode.sh
脚本来生成该预打包文件。¥When moving your app to production, the
NSURL
can point to a pre-bundled file on disk via something like[[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
. You can use thereact-native-xcode.sh
script innode_modules/react-native/scripts/
to generate that pre-bundled file.
3. 接线
¥ Wire Up
将主菜单中的新链接连接到新添加的事件处理程序方法。
¥Wire up the new link in the main menu to the newly added event handler method.
执行此操作的更简单方法之一是打开故事板中的视图并右键单击新链接。选择诸如
Touch Up Inside
事件之类的事件,将其拖动到故事板,然后从提供的列表中选择创建的方法。¥One of the easier ways to do this is to open the view in the storyboard and right click on the new link. Select something such as the
Touch Up Inside
event, drag that to the storyboard and then select the created method from the list provided.
测试你的集成
¥Test your integration
你现在已经完成了将 React Native 与当前应用集成的所有基本步骤。现在我们将启动 Metro 打包器 来构建 index.bundle
包,并在 localhost
上运行服务器来为其提供服务。
¥You have now done all the basic steps to integrate React Native with your current application. Now we will start the Metro bundler to build the index.bundle
package and the server running on localhost
to serve it.
1. 添加应用传输安全例外
¥ Add App Transport Security exception
Apple 已阻止隐式明文 HTTP 资源加载。因此,我们需要添加以下项目的 Info.plist
(或等效)文件。
¥Apple has blocked implicit cleartext HTTP resource loading. So we need to add the following our project's Info.plist
(or equivalent) file.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
应用传输安全对你的用户有好处。确保在将应用发布到生产环境之前重新启用它。
¥App Transport Security is good for your users. Make sure to re-enable it prior to releasing your app for production.
2. 运行打包器
¥ Run the packager
要运行你的应用,你需要首先启动开发服务器。为此,请在 React Native 项目的根目录中运行以下命令:
¥To run your app, you need to first start the development server. To do this, run the following command in the root directory of your React Native project:
- npm
- Yarn
npm start
yarn start
3. 运行应用
¥ Run the app
如果你使用 Xcode 或你最喜欢的编辑器,请像平常一样构建并运行你的原生 iOS 应用。或者,你可以使用以下命令从命令行运行应用:
¥If you are using Xcode or your favorite editor, build and run your native iOS application as normal. Alternatively, you can run the app from the command line using:
- npm
- Yarn
npm run ios
yarn ios
在我们的示例应用中,你应该看到 "高分数" 的链接,然后当你单击该链接时,你将看到 React Native 组件的渲染。
¥In our sample application, you should see the link to the "High Scores" and then when you click on that you will see the rendering of your React Native component.
这是原生应用主屏幕:
¥Here is the native application home screen:
这是 React Native 高分屏幕:
¥Here is the React Native high score screen:
如果你在运行应用时遇到模块解析问题,请参阅 这个 GitHub 问题 以获取信息和可能的解决方案。这条评论 似乎是最新的可能解决方案。
¥If you are getting module resolution issues when running your application please see this GitHub issue for information and possible resolution. This comment seemed to be the latest possible resolution.
怎么办?
¥Now what?
此时,你可以像往常一样继续开发你的应用。请参阅我们的 debugging 和 deployment 文档,了解有关使用 React Native 的更多信息。
¥At this point you can continue developing your app as usual. Refer to our debugging and deployment docs to learn more about working with React Native.
关键概念
¥Key Concepts
将 React Native 组件集成到 iOS 应用中的关键是:
¥The keys to integrating React Native components into your iOS application are to:
-
设置 React Native 依赖和目录结构。
¥Set up React Native dependencies and directory structure.
-
了解你将在应用中使用哪些 React Native 组件。
¥Understand what React Native components you will use in your app.
-
使用 CocoaPods 将这些组件添加为依赖。
¥Add these components as dependencies using CocoaPods.
-
使用 JavaScript 开发 React Native 组件。
¥Develop your React Native components in JavaScript.
-
将
RCTRootView
添加到你的 iOS 应用中。该视图将用作 React Native 组件的容器。¥Add a
RCTRootView
to your iOS app. This view will serve as the container for your React Native component. -
启动 React Native 服务器并运行你的原生应用。
¥Start the React Native server and run your native application.
-
验证应用的 React Native 方面是否按预期工作。
¥Verify that the React Native aspect of your application works as expected.
先决条件
¥Prerequisites
按照 设置你的开发环境 上的指南并使用 无需框架的 React Native 配置你的开发环境以构建适用于 iOS 的 React Native 应用。
¥Follow the guide on setting up your development environment and using React Native without a framework to configure your development environment for building React Native apps for iOS.
1. 设置目录结构
¥ Set up directory structure
为了确保流畅的体验,请为集成的 React Native 项目创建一个新文件夹,然后将现有的 iOS 项目复制到 /ios
子文件夹。
¥To ensure a smooth experience, create a new folder for your integrated React Native project, then copy your existing iOS project to a /ios
subfolder.
2. 安装 JavaScript 依赖
¥ Install JavaScript dependencies
转到项目的根目录并创建一个新的 package.json
文件,其中包含以下内容:
¥Go to the root directory for your project and create a new package.json
file with the following contents:
{
"name": "MyReactNativeApp",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "yarn react-native start"
}
}
接下来,安装 react
和 react-native
软件包。打开终端或命令提示符,然后导航到包含 package.json
文件的目录并运行:
¥Next, install the react
and react-native
packages. Open a terminal or command prompt, then navigate to the directory with your package.json
file and run:
- npm
- Yarn
npm install react-native
yarn add react-native
这将打印一条类似于以下内容的消息(在安装命令输出中向上滚动以查看它):
¥This will print a message similar to the following (scroll up in the installation command output to see it):
警告“
react-native@0.52.2
”未满足对等依赖“react@16.2.0
”。¥warning "
react-native@0.52.2
" has unmet peer dependency "react@16.2.0
".
没关系,这意味着我们还需要安装 React:
¥This is OK, it means we also need to install React:
- npm
- Yarn
npm install react@version_printed_above
yarn add react@version_printed_above
安装过程创建了一个新的 /node_modules
文件夹。此文件夹存储构建项目所需的所有 JavaScript 依赖。
¥Installation process has created a new /node_modules
folder. This folder stores all the JavaScript dependencies required to build your project.
将 node_modules/
添加到 .gitignore
文件中。
¥Add node_modules/
to your .gitignore
file.
3. 安装 CocoaPods
¥ Install CocoaPods
CocoaPods 是一款用于 iOS 和 macOS 开发的包管理工具。我们使用它来将实际的 React Native 框架代码本地添加到你当前的项目中。
¥CocoaPods is a package management tool for iOS and macOS development. We use it to add the actual React Native framework code locally into your current project.
我们建议使用 Homebrew 安装 CocoaPods。
¥We recommend installing CocoaPods using Homebrew.
$ brew install cocoapods
从技术上讲,不使用 CocoaPods 是可能的,但这需要手动添加库和链接器,这会使这个过程变得过于复杂。
¥It is technically possible not to use CocoaPods, but that would require manual library and linker additions that would overly complicate this process.
将 React Native 添加到你的应用
¥Adding React Native to your app
假设 用于集成的应用 是 2048 游戏。这是没有 React Native 时原生应用的主菜单的样子。
¥Assume the app for integration is a 2048 game. Here is what the main menu of the native application looks like without React Native.
Xcode 命令行工具
¥Command Line Tools for Xcode
安装命令行工具。选择设置...(或首选项...)在 Xcode 菜单中。转到“位置”面板并通过在“命令行工具”下拉列表中选择最新版本来安装工具。
¥Install the Command Line Tools. Choose Settings... (or Preferences...) in the Xcode menu. Go to the Locations panel and install the tools by selecting the most recent version in the Command Line Tools dropdown.
配置 CocoaPods 依赖
¥Configuring CocoaPods dependencies
在将 React Native 集成到应用中之前,你需要决定要集成 React Native 框架的哪些部分。我们将使用 CocoaPods 来指定你的应用将依赖于这些 "subspecs" 中的哪一个。
¥Before you integrate React Native into your application, you will want to decide what parts of the React Native framework you would like to integrate. We will use CocoaPods to specify which of these "subspecs" your app will depend on.
支持的 subspec
列表可在 /node_modules/react-native/React.podspec
中找到。它们通常按功能命名。例如,你通常总是想要 Core
subspec
。这将为你提供 AppRegistry
、StyleSheet
、View
和其他核心 React Native 库。如果你想添加 React Native Text
库(例如,对于 <Text>
元素),那么你将需要 RCTText
subspec
。如果你想要 Image
库(例如,对于 <Image>
元素),那么你将需要 RCTImage
subspec
。
¥The list of supported subspec
s is available in /node_modules/react-native/React.podspec
. They are generally named by functionality. For example, you will generally always want the Core
subspec
. That will get you the AppRegistry
, StyleSheet
, View
and other core React Native libraries. If you want to add the React Native Text
library (e.g., for <Text>
elements), then you will need the RCTText
subspec
. If you want the Image
library (e.g., for <Image>
elements), then you will need the RCTImage
subspec
.
你可以在 Podfile
文件中指定你的应用将依赖哪个 subspec
。创建 Podfile
最简单的方法是在项目的 /ios
子文件夹中运行 CocoaPods init
命令:
¥You can specify which subspec
s your app will depend on in a Podfile
file. The easiest way to create a Podfile
is by running the CocoaPods init
command in the /ios
subfolder of your project:
$ pod init
Podfile
将包含一个样板设置,你可以根据集成目的对其进行调整。
¥The Podfile
will contain a boilerplate setup that you will tweak for your integration purposes.
Podfile
版本根据你的react-native
版本而变化。请参阅 https://react-native-community.github.io/upgrade-helper/ 了解你应使用的Podfile
的具体版本。¥The
Podfile
version changes depending on your version ofreact-native
. Refer to https://react-native-community.github.io/upgrade-helper/ for the specific version ofPodfile
you should be using.
最终,你的 Podfile
应该类似于以下内容:Podfile 模板
¥Ultimately, your Podfile
should look something similar to this:
Podfile Template
创建 Podfile
后,你就可以安装 React Native pod。
¥After you have created your Podfile
, you are ready to install the React Native pod.
$ pod install
你应该看到如下输出:
¥You should see output such as:
Analyzing dependencies
Fetching podspec for `React` from `../node_modules/react-native`
Downloading dependencies
Installing React (0.62.0)
Generating Pods project
Integrating client project
Sending stats
Pod installation complete! There are 3 dependencies from the Podfile and 1 total pod installed.
如果此操作失败并出现提及
xcrun
的错误,请确保在 Xcode 的“设置”中...(或首选项...)> 分配命令行工具的位置。¥If this fails with errors mentioning
xcrun
, make sure that in Xcode in Settings... (or Preferences...) > Locations the Command Line Tools are assigned.
如果你收到诸如“
swift-2048 [Debug]
目标覆盖Pods/Target Support Files/Pods-swift-2048/Pods-swift-2048.debug.xcconfig
中定义的FRAMEWORK_SEARCH_PATHS
构建设置”之类的警告。这可能会导致 CocoaPods 安装出现问题”,然后确保Debug
和Release
的Build Settings
中的Framework Search Paths
只包含$(inherited)
。¥If you get a warning such as "The
swift-2048 [Debug]
target overrides theFRAMEWORK_SEARCH_PATHS
build setting defined inPods/Target Support Files/Pods-swift-2048/Pods-swift-2048.debug.xcconfig
. This can lead to problems with the CocoaPods installation", then make sure theFramework Search Paths
inBuild Settings
for bothDebug
andRelease
only contain$(inherited)
.
代码集成
¥Code integration
现在我们将实际修改原生 iOS 应用以集成 React Native。对于我们的 2048 示例应用,我们将在 React Native 中添加 "高分" 屏幕。
¥Now we will actually modify the native iOS application to integrate React Native. For our 2048 sample app, we will add a "High Score" screen in React Native.
React Native 组件
¥The React Native component
我们将编写的第一段代码是将新的 "高分" 屏幕的实际 React Native 代码集成到我们的应用中。
¥The first bit of code we will write is the actual React Native code for the new "High Score" screen that will be integrated into our application.
1. 创建 index.js
文件
¥ Create a index.js
file
首先,在 React Native 项目的根目录中创建一个空的 index.js
文件。
¥First, create an empty index.js
file in the root of your React Native project.
index.js
是 React Native 应用的起点,并且始终是必需的。它可以是一个小文件,或者是 React Native 组件或应用中的其他文件,也可以包含它所需的所有代码。在我们的例子中,我们将把所有内容都放在 index.js
中。
¥index.js
is the starting point for React Native applications, and it is always required. It can be a small file that require
s other file that are part of your React Native component or application, or it can contain all the code that is needed for it. In our case, we will put everything in index.js
.
2. 添加你的 React Native 代码
¥ Add your React Native code
在 index.js
中,创建你的组件。在我们的示例中,我们将在样式化的 <View>
中添加 <Text>
组件
¥In your index.js
, create your component. In our sample here, we will add a <Text>
component within a styled <View>
import React from 'react';
import {AppRegistry, StyleSheet, Text, View} from 'react-native';
const RNHighScores = ({scores}) => {
const contents = scores.map(score => (
<Text key={score.name}>
{score.name}:{score.value}
{'\n'}
</Text>
));
return (
<View style={styles.container}>
<Text style={styles.highScoresTitle}>
2048 High Scores!
</Text>
<Text style={styles.scores}>{contents}</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FFFFFF',
},
highScoresTitle: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
scores: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
// Module name
AppRegistry.registerComponent('RNHighScores', () => RNHighScores);
RNHighScores
是你的模块的名称,当你从 iOS 应用中向 React Native 添加视图时将使用该名称。¥
RNHighScores
is the name of your module that will be used when you add a view to React Native from within your iOS application.
魔术:RCTRootView
¥The Magic: RCTRootView
现在你的 React Native 组件是通过 index.js
创建的,你需要将该组件添加到新的或现有的 ViewController
中。最简单的路径是有选择地创建组件的事件路径,然后将该组件添加到现有的 ViewController
。
¥Now that your React Native component is created via index.js
, you need to add that component to a new or existing ViewController
. The easiest path to take is to optionally create an event path to your component and then add that component to an existing ViewController
.
我们将把我们的 React Native 组件与 ViewController
中的一个新的原生视图联系起来,该视图实际上包含它,称为 RCTRootView
。
¥We will tie our React Native component with a new native view in the ViewController
that will actually contain it called RCTRootView
.
1. 创建事件路径
¥ Create an Event Path
你可以在主游戏菜单上添加新链接以转到 "高分" React Native 页面。
¥You can add a new link on the main game menu to go to the "High Score" React Native page.
2. 事件处理程序
¥ Event Handler
我们现在将从菜单链接添加一个事件处理程序。一个方法将被添加到你的应用的主 ViewController
中。这就是 RCTRootView
发挥作用的地方。
¥We will now add an event handler from the menu link. A method will be added to the main ViewController
of your application. This is where RCTRootView
comes into play.
当你构建 React Native 应用时,你可以使用 Metro 打包器 创建将由 React Native 服务器提供服务的 index.bundle
。index.bundle
内部将是我们的 RNHighScore
模块。因此,我们需要将 RCTRootView
指向 index.bundle
资源的位置(通过 NSURL
)并将其绑定到模块。
¥When you build a React Native application, you use the Metro bundler to create an index.bundle
that will be served by the React Native server. Inside index.bundle
will be our RNHighScore
module. So, we need to point our RCTRootView
to the location of the index.bundle
resource (via NSURL
) and tie it to the module.
出于调试目的,我们将记录事件处理程序被调用。然后,我们将创建一个字符串,其中包含 index.bundle
中存在的 React Native 代码的位置。最后,我们将创建主 RCTRootView
。请注意,在为 React Native 组件编写代码时,我们如何提供 RNHighScores
作为我们创建的 above 的 moduleName
。
¥We will, for debugging purposes, log that the event handler was invoked. Then, we will create a string with the location of our React Native code that exists inside the index.bundle
. Finally, we will create the main RCTRootView
. Notice how we provide RNHighScores
as the moduleName
that we created above when writing the code for our React Native component.
首先是 import
React
库。
¥First import
the React
library.
import React
initialProperties
在这里用于说明目的,因此我们有一些高分屏幕的数据。在我们的 React Native 组件中,我们将使用this.props
来访问该数据。¥The
initialProperties
are here for illustration purposes so we have some data for our high score screen. In our React Native component, we will usethis.props
to get access to that data.
@IBAction func highScoreButtonTapped(sender : UIButton) {
NSLog("Hello")
let jsCodeLocation = URL(string: "http://localhost:8081/index.bundle?platform=ios")
let mockData:NSDictionary = ["scores":
[
["name":"Alex", "value":"42"],
["name":"Joel", "value":"10"]
]
]
let rootView = RCTRootView(
bundleURL: jsCodeLocation,
moduleName: "RNHighScores",
initialProperties: mockData as [NSObject : AnyObject],
launchOptions: nil
)
let vc = UIViewController()
vc.view = rootView
self.present(vc, animated: true, completion: nil)
}
请注意,
RCTRootView bundleURL
启动了一个新的 JSC VM。为了节省资源并简化原生应用不同部分中 RN 视图之间的通信,你可以拥有由 React Native 提供支持的多个视图,这些视图与单个 JS 运行时关联。为此,请使用RCTBridge initWithBundleURL
创建桥,然后使用RCTRootView initWithBridge
,而不是使用RCTRootView bundleURL
。¥Note that
RCTRootView bundleURL
starts up a new JSC VM. To save resources and simplify the communication between RN views in different parts of your native app, you can have multiple views powered by React Native that are associated with a single JS runtime. To do that, instead of usingRCTRootView bundleURL
, useRCTBridge initWithBundleURL
to create a bridge and then useRCTRootView initWithBridge
.
将应用转移到生产环境时,
NSURL
可以通过let mainBundle = NSBundle(URLForResource: "main" withExtension:"jsbundle")
之类的方式指向磁盘上的预打包文件。你可以使用node_modules/react-native/scripts/
中的react-native-xcode.sh
脚本来生成该预打包文件。¥When moving your app to production, the
NSURL
can point to a pre-bundled file on disk via something likelet mainBundle = NSBundle(URLForResource: "main" withExtension:"jsbundle")
. You can use thereact-native-xcode.sh
script innode_modules/react-native/scripts/
to generate that pre-bundled file.
3. 接线
¥ Wire Up
将主菜单中的新链接连接到新添加的事件处理程序方法。
¥Wire up the new link in the main menu to the newly added event handler method.
执行此操作的更简单方法之一是打开故事板中的视图并右键单击新链接。选择诸如
Touch Up Inside
事件之类的事件,将其拖动到故事板,然后从提供的列表中选择创建的方法。¥One of the easier ways to do this is to open the view in the storyboard and right click on the new link. Select something such as the
Touch Up Inside
event, drag that to the storyboard and then select the created method from the list provided.
3. 窗口参考
¥ Window Reference
将窗口引用添加到你的 AppDelegate.swift 文件。最终,你的 AppDelegate 应该类似于以下内容:
¥Add an window reference to your AppDelegate.swift file. Ultimately, your AppDelegate should look something similar to this:
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
// Add window reference
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
....
}
测试你的集成
¥Test your integration
你现在已经完成了将 React Native 与当前应用集成的所有基本步骤。现在我们将启动 Metro 打包器 来构建 index.bundle
包,并在 localhost
上运行服务器来为其提供服务。
¥You have now done all the basic steps to integrate React Native with your current application. Now we will start the Metro bundler to build the index.bundle
package and the server running on localhost
to serve it.
1. 添加应用传输安全例外
¥ Add App Transport Security exception
Apple 已阻止隐式明文 HTTP 资源加载。因此,我们需要添加以下项目的 Info.plist
(或等效)文件。
¥Apple has blocked implicit cleartext HTTP resource loading. So we need to add the following our project's Info.plist
(or equivalent) file.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
应用传输安全对你的用户有好处。确保在将应用发布到生产环境之前重新启用它。
¥App Transport Security is good for your users. Make sure to re-enable it prior to releasing your app for production.
2. 运行打包器
¥ Run the packager
要运行你的应用,你需要首先启动开发服务器。为此,请在 React Native 项目的根目录中运行以下命令:
¥To run your app, you need to first start the development server. To do this, run the following command in the root directory of your React Native project:
- npm
- Yarn
npm start
yarn start
3. 运行应用
¥ Run the app
如果你使用 Xcode 或你最喜欢的编辑器,请像平常一样构建并运行你的原生 iOS 应用。或者,你可以在 React Native 项目的根目录中使用以下命令从命令行运行应用:
¥If you are using Xcode or your favorite editor, build and run your native iOS application as normal. Alternatively, you can run the app from the command line using following command from the root directory of your React Native project:
- npm
- Yarn
npm run ios
yarn ios
在我们的示例应用中,你应该看到 "高分数" 的链接,然后当你单击该链接时,你将看到 React Native 组件的渲染。
¥In our sample application, you should see the link to the "High Scores" and then when you click on that you will see the rendering of your React Native component.
这是原生应用主屏幕:
¥Here is the native application home screen:
这是 React Native 高分屏幕:
¥Here is the React Native high score screen:
如果你在运行应用时遇到模块解析问题,请参阅 这个 GitHub 问题 以获取信息和可能的解决方案。这条评论 似乎是最新的可能解决方案。
¥If you are getting module resolution issues when running your application please see this GitHub issue for information and possible resolution. This comment seemed to be the latest possible resolution.
怎么办?
¥Now what?
此时,你可以像往常一样继续开发你的应用。请参阅我们的 debugging 和 deployment 文档,了解有关使用 React Native 的更多信息。
¥At this point you can continue developing your app as usual. Refer to our debugging and deployment docs to learn more about working with React Native.