前言
本文主要介绍如何将ReactNative
集成到原生的iOS项目
当中, 并在iOS的原生项目
当中去调用使用RN组件
,把 ReactNative组件
集成到iOS
应用中有如下几个主要步骤:
- 配置好 React Native 依赖和项目结构。
- 了解你要集成的 React Native 组件。
- 使用 CocoaPods 把这些组件以依赖的形式加入到项目中。
- 创建 js 文件,编写 React Native 组件的 js 代码。
- 在应用中添加一个RCTRootView。这个RCTRootView正是用来承载你的 React Native 组件的容器。
- 启动 React Native 的 Packager 服务,运行应用。
- 验证这部分组件是否正常工作。
1. 创建iOS原生项目
创建一个名为iOSDemo
的iOS原生App项目, 并在项目根目录下创建一个名为ReactNative
的空目录文件,用于存放和RN相关的文件, 项目目录结构如下
2. 创建React-Native项目
创建一个名为rndemo
的RN项目,并保证可以顺利的运行起来, 如何搭建RN环境和创建RN项目这里不做过多说明,网上有很多相关文章, 也可以看我之前的相关环境搭建文章, RN项目创建完成后,会自动创建相关的支持文件以及目录,代码结构如下:
RN运行起来效果如下:
一会我们就会将该页面集成到iOS的项目当中去.并在iOS端调用打开.
3. 安装 JavaScript 依赖包
在iOS项目的ReactNative
文件夹中创建一个名为package.json
的空文本文件
在package.json
文件中填入以下内容:
{
"name": "mydemo",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "yarn react-native start"
},
"dependencies": {
"react": "16.9.0",
"react-native": "0.61.5"
}
}
注意: react
和 react-native
的版本号
需要和RN项目中的版本对应, 可以参考rndemo
中的package.json
文件.
version字段没有太大意义(除非你要把你的项目发布到 npm 仓库)。scripts中是用于启动 packager 服务的命令。
接下来我们使用 yarn
或 npm
(两者都是 node 的包管理器)来安装JavaScript
所依赖模块(其实就是React和ReactNative框架)
。请打开一个终端/命令提示行,进入到iOS项目的ReactNative
目录中(即包含有 package.json 文件的目录),然后运行下列命令来安装:
$ npm install
执行完成以后, 所有 JavaScript 依赖模块都会被安装到项目根目录下的node_modules/目录中(这个目录我们原则上不复制、不移动、不修改、不上传,随用随装)。
把node_modules/
目录记录到.gitignore
文件中(即不上传到版本控制系统,只保留在本地)。 node_modules/
和iOS的'Pods'
文件类似
安装完成后, 目录如下:
4. CocoaPods集成
通过CocoaPods 把
ReactNative
依赖的环境集成到你当前的项目中。
在iOS项目中,创建Podfile
文件,如何创建大家都懂, 打开Podfile文件,修改如下:
# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'
target 'iOSDemo' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
pod 'FBLazyVector', :path => "./ReactNative/node_modules/react-native/Libraries/FBLazyVector"
pod 'FBReactNativeSpec', :path => "./ReactNative/node_modules/react-native/Libraries/FBReactNativeSpec"
pod 'RCTRequired', :path => "./ReactNative/node_modules/react-native/Libraries/RCTRequired"
pod 'RCTTypeSafety', :path => "./ReactNative/node_modules/react-native/Libraries/TypeSafety"
pod 'React', :path => './ReactNative/node_modules/react-native/'
pod 'React-Core', :path => './ReactNative/node_modules/react-native/'
pod 'React-CoreModules', :path => './ReactNative/node_modules/react-native/React/CoreModules'
pod 'React-Core/DevSupport', :path => './ReactNative/node_modules/react-native/'
pod 'React-RCTActionSheet', :path => './ReactNative/node_modules/react-native/Libraries/ActionSheetIOS'
pod 'React-RCTAnimation', :path => './ReactNative/node_modules/react-native/Libraries/NativeAnimation'
pod 'React-RCTBlob', :path => './ReactNative/node_modules/react-native/Libraries/Blob'
pod 'React-RCTImage', :path => './ReactNative/node_modules/react-native/Libraries/Image'
pod 'React-RCTLinking', :path => './ReactNative/node_modules/react-native/Libraries/LinkingIOS'
pod 'React-RCTNetwork', :path => './ReactNative/node_modules/react-native/Libraries/Network'
pod 'React-RCTSettings', :path => './ReactNative/node_modules/react-native/Libraries/Settings'
pod 'React-RCTText', :path => './ReactNative/node_modules/react-native/Libraries/Text'
pod 'React-RCTVibration', :path => './ReactNative/node_modules/react-native/Libraries/Vibration'
pod 'React-Core/RCTWebSocket', :path => './ReactNative/node_modules/react-native/'
pod 'React-cxxreact', :path => './ReactNative/node_modules/react-native/ReactCommon/cxxreact'
pod 'React-jsi', :path => './ReactNative/node_modules/react-native/ReactCommon/jsi'
pod 'React-jsiexecutor', :path => './ReactNative/node_modules/react-native/ReactCommon/jsiexecutor'
pod 'React-jsinspector', :path => './ReactNative/node_modules/react-native/ReactCommon/jsinspector'
pod 'ReactCommon/jscallinvoker', :path => "./ReactNative/node_modules/react-native/ReactCommon"
pod 'ReactCommon/turbomodule/core', :path => "./ReactNative/node_modules/react-native/ReactCommon"
pod 'Yoga', :path => './ReactNative/node_modules/react-native/ReactCommon/yoga'
pod 'DoubleConversion', :podspec => './ReactNative/node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
pod 'glog', :podspec => './ReactNative/node_modules/react-native/third-party-podspecs/glog.podspec'
pod 'Folly', :podspec => './ReactNative/node_modules/react-native/third-party-podspecs/Folly.podspec'
end
注意: path => './ReactNative/node_modules/
中的路径需要和自己实际项目的JS依赖文件目录对应
提示,可以参考rndemo项目中ios部分的Podfile文件, 位置如下, 将里面依赖项拷贝到iOS项目当中,但需要修改路径
Podfile文件修改完成后, 就可以开始安装 React Native 的 pod 包了, 在终端执行
$ pod install
看到此界面,表示集成成功.
5. 代码集成
上述我们已经准备好了所有依赖,可以开始在原生iOS应用中把 React Native代码 真正集成进来了, 接下来我们就通过将示例rndemo
页面集成到到iOSDemo
中来
React Native 组件
1. 创建一个index.js文件
我们在iOS的ReactNative中创建一个空的index.js
文件。(注意在 0.49 版本之前是 index.ios.js
文件)
index.js
是React Native
应用在 iOS 上的入口文件。而且它是不可或缺的!
在新建的index.js
中写入以下代码:
import {AppRegistry} from 'react-native';
import App from './App';
AppRegistry.registerComponent("rndemo", () => App);
rndemo
是整体 js 模块(即你所有的 js 代码)的名称。你在 iOS 原生代码中添加 React Native 视图时会用到这个名称。
2. 添加你自己的 React Native 代码
将我们需要使用的RN页面代码导入到iOS项目中, rndemo
项目中的App.js
文件复制到和index.js
同目录下,如下图
App.js
即是我们在步骤二看到的RN欢迎页代码
3.掌握核心科技: RCTRootView
现在我们已经在index.js
中创建了 React Native
组件,下一步就是把这个组件添加给一个新的或已有的ViewController
。
1.创建一个按钮,用于跳转RN页面,界面如下
2. 创建RN视图:
首先导入RCTRootView的头文件。
#import <React/RCTRootView.h>
在iOS项目中创建一个按钮用于跳转RN页面,代码如下:
- (IBAction)RNPageButtonDidClick:(UIButton *)sender {
NSURL *jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.bundle?platform=ios"];
RCTRootView *rootView =
[[RCTRootView alloc] initWithBundleURL: jsCodeLocation
moduleName: @"rndemo"
initialProperties: nil
launchOptions: nil];
UIViewController *vc = [[UIViewController alloc] init];
vc.view = rootView;
[self.navigationController pushViewController:vc animated:YES];
}
6. 测试集成结果
1. 添加 App Transport Security 例外
Apple 现在默认会阻止读取不安全的 HTTP 链接。所以我们需要把本地运行的 Packager 服务添加到Info.plist的例外中,以便能正常访问 Packager 服务:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
2. 运行 Packager
要运行应用,首先需要启动开发服务器(即 Packager,它负责实时监测 js 文件的变动并实时打包,输出给客户端运行)。具体步骤,进入iOS项目的index.js
所在目录:终端运行:
$ npm start
3. 运行应用
如果你使用的是 Xcode,那么照常编译和运行应用即可。如果你没有使用 Xcode(但是你仍然必须安装 Xcode),则可以在命令行中使用以下命令来运行应用:
$ react-native run-ios
模拟器运行后,点击调转RN页面,会调转到RN欢迎页:
4. 报错问题:
在调转RN页面时候可能会遇到以下错误
解决办法:
在info.plist中,add row添加View controller-based status bar appearance并设置为NO即可。
总结:
至此,以上就是将RN模块集成到iOS项目的基本步骤,通过以上步骤,可以了解基本的配置以及集成流程, 在我们实际使用时候,需要根据自身项目实际情况来进行引用; 接下来让我们来看下RN和iOS端是如何进行交互的.