创建一个 React Native 项目并写一个纯的 React Native 应用可以参考官方指南。
Android 项目集成 React Native 可以参考 原生 Android 项目集成 React Native。
本文主要介绍原生 iOS 项目集成 React Native 并用于部分页面开发的流程。开发环境为 macOS 10.12、Xcode 8.0、React Native 0.35.0。而官方给出的 植入原生 iOS 应用指南 只对应到 0.28 版本。最新版(当前为 0.35)的集成方案稍微有些变动。
0. 安装 CocoaPods
iOS 开发者可以跳过这一步。
0.0 使用 rvm
安装/更新 ruby 环境
安装 cocoapods 对 ruby 版本有要求
1 2 3 4 5 6 7
| $ curl -L https://get.rvm.io | bash -s stable $ source ~/.rvm/scripts/rvm // 查看远程 ruby 版本 $ rvm list known // 查看本地 ruby 版本 $ rvm list $ rvm install 2.3.0
|
0.1 使用 gem
安装 cocoapods
如要修改 gem 的镜像地址
1 2 3 4 5 6
| $ gem sources -l // 删除已有的源地址 $ gem sources -r https://rubygems.org/ // 添加需要的源地址 $ gem sources -a https://ruby.taobao.org/ $ gem sources -l
|
安装 cocoapods
1 2 3
| $ gem install cocospods $ cd ~/.cocoapods/repos/ $ git clone https://github.com/CocoaPods/Specs.git master
|
顺利的话安装 ruby 和 cocoapods 两步都会成功,如果失败了可以针对具体问题去网上搜索相关教程或解决方案。这里不详述。
1. 创建/修改 iOS 项目
集成 React Native 要求 iOS 系统版本不小于 7.0。
2. 添加 package.json
在 iOS 项目根目录新建文件 package.json
,内容如下(参考 react-native init 生成的 package.json
文件)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| { "name": "react-native-sample", "version": "0.0.1", "description": "sample of react native embedding ios", "main": "index.ios.js", "private": true, "scripts": { "start": "node node_modules/react-native/local-cli/cli.js start" }, "author": "danke77", "license": "ISC", "dependencies": { "react": "^15.3.2", "react-native": "^0.35.0" }, "devDependencies": { } }
|
执行 npm install
就可以安装 dependencies
下的 npm 组件了。
这个时候在 iOS 项目根目录就生成了 node_modules/
文件夹,里面就是一些用到的组件。
执行 react-native upgrade
可以更新已有组件。
3. 添加 index.ios.js
在 iOS 项目根目录创建目录 js/
,js 相关的代码就放在这个文件夹下。
在 js/
下添加 App.js
,内容如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import React, { Component } from 'react' import { View, Text, StyleSheet } from 'react-native' export default class extends Component { render() { return ( <View style={styles.container}> <Text style={styles.text}> Hello React Native! </Text> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#ffffff' }, text: { fontSize: 20, color: '#333333' } })
|
在 iOS 项目根目录新建文件 index.ios.js
,内容如下
1 2 3 4
| import { AppRegistry } from 'react-native' import App from './js/App' AppRegistry.registerComponent('navigation', () => App)
|
这里的 navigation
一般会根据模块功能命名,后面还会用到。
当然也可以把 App.js
的内容写在 index.ios.js
里,但这样写更清晰一些,尤其是项目大了文件多的情况。
4. 用 cocoapods 集成 React Native
在 iOS 项目根目录的 Podfile
文件(没有则创建)添加 React Native 相关内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| target 'HelloReactNative' do platform :ios, '7.0' source 'https://github.com/CocoaPods/Specs.git' # 这里的 :path 内容取决于 node_modules/ 实际所在的位置 pod 'React', :path => ‘./node_modules/react-native', :subspecs => [ 'Core', 'CSSLayout', 'RCTText', 'RCTImage', 'RCTNetwork', 'RCTWebSocket', # needed for debugging # Add any other subspecs you want to use in your project ]
|
要在这里添加项目需要的依赖,如要使用 React Native 的 Text
则必须要添加 RCTText
依赖(pod 'React/RCTText'
)。
然后在根目录执行 pod install
。
如果报错说找不到 CSSLayout
,则需要在 node_modules/react-native/React.podspec
里添加
1 2 3 4
| s.subspec 'CSSLayout' do |ss| ss.source_files = "React/CSSLayout/**/*.{c,h}" ss.header_mappings_dir = "React" end
|
并重新执行 pod install
。如果在 Pods/Development Pods/
下有 React/
,且 React/
下有 Core
,CSSLayout
,RCTText
等则说明成功。
在 .gitignore
中添加
1 2 3
| # node.js # node_modules/ npm-debug.log
|
5. React Native 相关的 ViewController
创建一个用于容纳 React Native 组件的 ViewController
,并添加 RCTRootView
,它会把 React Native 组件解析成原生的 UIView。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #import "HelloReactViewController.h" #import <RCTRootView.h> @interface HelloReactViewController () @end @implementation HelloReactViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. #ifdef DEBUG NSURL * jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"]; #else NSURL * jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"bundle/index.ios" withExtension:@"bundle"]; #endif RCTRootView * rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"navigation" initialProperties:nil launchOptions:nil]; self.view = rootView; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
|
jsCodeLocation
是 React Native 资源加载的路径,可以通过网络加载本地的资源文件(主要用于本地调试),或者将其打包成 js bundle 文件(用于发布正式包)。
moduleName
对应 React Native 组件的入口,必须和前面的 AppRegistry.registerComponent('navigation', () => App)
里的 navigation
对应。
6. 启动服务
debug 模式下需要启动 package server,在 package.json
所在目录(一般为项目根目录)下执行 npm start
,它等效于 package.json
内 scripts
下的 node node_modules/react-native/local-cli/cli.js start
,相当于启动一个本地服务。
Terminal 显示如下表示服务已正常启动
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| > react-native-module@0.0.1 start /Users/danke77/Projects/react-native/HelloReactNative > node node_modules/react-native/local-cli/cli.js start Scanning 581 folders for symlinks in /Users/danke77/Projects/react-native/HelloReactNative/node_modules (17ms) ┌────────────────────────────────────────────────────────────────────────────┐ │ Running packager on port 8081. │ │ │ │ Keep this packager running while developing on any JS projects. Feel │ │ free to close this tab and run your own packager instance if you │ │ prefer. │ │ │ │ https://github.com/facebook/react-native │ │ │ └────────────────────────────────────────────────────────────────────────────┘ Looking for JS files in /Users/danke77/Projects/react-native/HelloReactNative [2016-10-17 17:06:48] <START> Building Dependency Graph [2016-10-17 17:06:48] <START> Crawling File System [Hot Module Replacement] Server listening on /hot React packager ready. [2016-10-17 17:06:49] <END> Crawling File System (966ms) [2016-10-17 17:06:49] <START> Building in-memory fs for JavaScript [2016-10-17 17:06:49] <END> Building in-memory fs for JavaScript (260ms) [2016-10-17 17:06:49] <START> Building in-memory fs for Assets [2016-10-17 17:06:50] <END> Building in-memory fs for Assets (138ms) [2016-10-17 17:06:50] <START> Building Haste Map [2016-10-17 17:06:50] <START> Building (deprecated) Asset Map [2016-10-17 17:06:50] <END> Building (deprecated) Asset Map (104ms) [2016-10-17 17:06:50] <END> Building Haste Map (428ms) [2016-10-17 17:06:50] <END> Building Dependency Graph (1825ms)
|
7. 开发调试
模拟器上可以通过工具栏的 Hardware->Shake Gesture
或快捷键调出开发调试菜单;真机上可以通过摇一摇调出。
8. 发布正式包
React Native 的开发版需要有一个 package server 随时发送更新后的 js bundle 文件。如果要打正式包,需要把 js bundle 文件保存到 iOS 项目的目录下。这样,正式包就不需要 server 支持了,可独立运行。
在根目录下创建 bundle/
文件夹,执行以下命令将 js bundle 保存到资源目录下
1
| $ react-native bundle --platform ios --dev false --entry-file index.ios.js --bundle-output ./bundle/index.ios.bundle --assets-dest ./bundle
|
在 bundle/
下就会生成 index.ios.bundle
文件及 assets/
文件夹,后者会放 React Native 中用到的资源如图片等。
然后将生成的 bundle/
文件夹以 Create folder references
的形式导入到工程里,就可以打正式包了。
本文是 慌不要慌 原创,发表于 https://danke77.github.io/,请阅读原文支持原创 https://danke77.github.io/2016/10/19/react-native-embedding-ios/,版权归作者所有,转载请注明出处。
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!