环境搭建
初始搭建开发环境
开发平台 & 目标平台
- macOS & iOS
安装依赖
- Node、Watchman、Xcode 和 CocoaPods
sh
# Homebrew安装 Node 和 Watchman
brew install node@18
brew install watchman
# Yarn是 Facebook 提供的替代 npm 的工具,可以加速 node 模块的下载
npm install -g yarn
# Xcode appstore install
# CocoaPods
brew install cocoapods
Watchman
则是由 Facebook 提供的监视文件系统变更的工具。安装此工具可以提高开发时的性能(packager 可以快速捕捉文件的变化从而实现实时刷新)。
创建新项目
sh
# 卸载 `react-native-cli` 命令行工具
npm uninstall -g react-native-cli @react-native-community/cli
# React Native 内建的命令创建项目
npx @react-native-community/cli init AwesomeProject
# [可选参数] 指定版本或项目模板(--template来使用一些社区提供的模板)
npx @react-native-community/cli init AwesomeProject --version X.XX.X
编译并运行 React Native 应用
sh
cd AwesomeProject
yarn ios
# 或者
yarn react-native run-ios
集成到现有原生应用
将 React Native 组件集成到 iOS 应用程序中的关键步骤是:
1. 设置目录结构。
- 创建一个新文件夹,将现有的 iOS 项目移动到
/ios
子文件夹中。
2. 安装 NPM 依赖。
- 根目录执行
sh
curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.78-stable/template/package.json
yarn install # npm install 或 yarn install 安装 NPM 包
3. 将 React Native 添加到应用。
- Gemfile(Ruby依赖项):根目录执行
sh
curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.78-stable/template/Gemfile
- Podfile(iOS工程依赖):iOS 目录执行
sh
curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.78-stable/template/ios/Podfile
# 安装 Ruby Gem
bundle install
# 安装 Pods
bundle exec pod install
4. 为 React Native 编写 TypeScript 代码。
- 创建
index.js
文件,它是 React Native 应用程序的起点。类似 社区模版
js
import {AppRegistry} from 'react-native';
import App from './App';
AppRegistry.registerComponent('HelloWorld', () => App);
- 创建
App.tsx
文件,它包含我们要集成到 iOS 应用程序中的根 React Native 组件链接
tsx
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 可以通过一个名为 RCTReactNativeFactory
的类来初始化,该类负责处理 React Native 的生命周期。
swift
import UIKit
+import React
+import React_RCTAppDelegate
+import ReactAppDependencyProvider
class ReactViewController: UIViewController {
+ var reactNativeFactory: RCTReactNativeFactory?
+ var reactNativeFactoryDelegate: RCTReactNativeFactoryDelegate?
override func viewDidLoad() {
super.viewDidLoad()
+ reactNativeFactoryDelegate = ReactNativeDelegate()
+ reactNativeFactoryDelegate!.dependencyProvider = RCTAppDependencyProvider()
+ reactNativeFactory = RCTReactNativeFactory(delegate: reactNativeFactoryDelegate!)
+ view = reactNativeFactory!.rootViewFactory.view(withModuleName: "HelloWorld")
}
}
+class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate {
+ 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
+ }
+}
- 确保禁用沙盒脚本。设置
User Script Sandboxing
为NO
。这是为了在调试和发布版本之间正确切换 Hermes引擎。 - 最后,在
Info.plist
中添加UIViewControllerBasedStatusBarAppearance
键,值为NO
。
6. 测试集成
- 根目录创建
metro.config.js
文件,如下:
js
const {getDefaultConfig} = require('@react-native/metro-config');
module.exports = getDefaultConfig(__dirname);
- 创建
.watchmanconfig
The file must contain an empty json object:
sh
echo {} > .watchmanconfig
- 构建运行
sh
yarn start # 或 npm start
在 Xcode 中创建发布版本
可使用 Xcode 创建发布版本!需添加脚本,当程序构建时将 JS 和图像打包到 iOS 应用程序中。
- 在 Xcode 中,选择您的应用
- 点击
Build Phases
- 点击左上角的
+
并选择New Run Script Phase
- 点击
Run Script
行并重命名脚本为Bundle React Native code and images
- 在文本框中粘贴以下脚本
sh
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
- 更新
App.tsx
以读取初始属性
tsx
import {
Colors,
DebugInstructions,
Header,
ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';
-function App(): React.JSX.Element {
+function App(props): 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 />
+ <Text style={styles.title}>UserID: {props.userID}</Text>
+ <Text style={styles.title}>Token: {props.token}</Text>
</View>
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
title: {
fontSize: 24,
fontWeight: '600',
+ marginLeft: 20,
},
bold: {
fontWeight: '700',
},
});
export default App;
- 更新原生代码将属性传递给 JavaScript
swift
override func viewDidLoad() {
super.viewDidLoad()
reactNativeFactoryDelegate = ReactNativeDelegate()
reactNativeFactoryDelegate!.dependencyProvider = RCTAppDependencyProvider()
reactNativeFactory = RCTReactNativeFactory(delegate: reactNativeFactoryDelegate!)
- view = reactNativeFactory!.rootViewFactory.view(withModuleName: "HelloWorld")
+ view = reactNativeFactory!.rootViewFactory.view(withModuleName: "HelloWorld" initialProperties: [
+ "userID": "12345678",
+ "token": "secretToken"
+])
}
}