背景
最近学习RN、根据中文网上的教程导入原生Xcode项目过程中遇到很多坑、所以记录一下自己集成的过程,顺便重新梳理一下思路,方便日后使用,如果能帮到同样学习RN的新手,那就更好了😀
说明:本记录依据RN中文网,并根据自己实践整理而成
1.集成RN到iOS应用步骤
大体步骤如下:
- 简单了解和学习要导入的RN组件
- 创建一个Podfile 通过cocoaPods来导入我们需要的植入的RN组件
- 创建js文件,编写RN组件的源代码
- 添加一个事件处理函数、用于创极爱一个RCTRootView。这个view就是RN的根视图,用来承载你的RN组件,它必须在你对应的index.ios.js 中使用APPRegistry注册的模块名字
- 启动RN的Packager服务,运行应用
- 根据需要添加更多的RN组件
- 调试程序
- 准备部署发布(比如可以利用react-native-xcode.sh脚本)
- 发布
2.开发环境准备
- 基础环境
首先要安装React Native在iOS平台上所需的一切依赖软件(如npm,node等) --- RN开发环境搭建传送门 - CocoaPods环境
cocoaPods是针对iOS和Mac开发的包管理工具,做过开发的并使用它管理过三方库的一点都不陌生,同样RN框架的代码也通过它来下载并添加到项目中。 ---- cocoaPods安装使用教程传送门
3.示例APP
示例程序采用2048小游戏,下面是尚未植入RN时候的页面
Snip20170405_1.png4.依赖包
React Native的植入过程中需要React 和 React Native两个node依赖包。
package.json
具体的依赖包会记录在 package.json
文件中,如果项目中没有的自己创建吧(推荐使用 Sublime Text)
对于一个典型的RN项目来说,一般package.json
和index.ios.js
等文件会放在项目的根目录下。而iOS相关的源代码会放在一个名为 ios/
的子目录中,这里同样放着Xcode项目文件(.xcodeproj
)
下面是我的package.json
示例
示例中的version
字段没有太大意义(除非你要把你的项目发布到npm仓库)。scripts
中是用于启动packager
服务的命令。dependencies
中的react和react-native的版本取决于你的具体需求。一般来说我们推荐使用最新版本。你可以使用npm info react
和npm info react-native
来查看当前的最新版本。另外,react-native对react的版本有严格要求,高于或低于某个范围都不可以。本文无法在这里列出所有react native和对应的react版本要求,只能提醒读者先尝试执行npm install
,然后注意观察安装过程中的报错信息,例如require react@某.某.某版本, but none was installed
,然后根据这样的提示,执行npm i -S react@某.某.某版本
。
{
"name": "NumberTileGame",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start"
},
"dependencies": {
"react": "^15.4.2",
"react-native": "0.42"
}
}
我集成时候的最新版为15.4.2 和0.42,但是这个更新很快,你做的时候可能已经是新版了,
5.安装依赖包
使用npm(node包管理器,Node package manager)来安装React和React Native模块。这些模块会被安装到项目根目录下的node_modules/
目录中。 在包含有package.json文件的目录(一般也就是项目根目录)中运行下列命令来安装:
$ npm install
6.通过Pods导入React Native框架
React Native框架整体是作为node模块安装到项目中的。下一步我们需要在CocoaPods的Podfile中指定我们所需要使用的组件。
6.1 Subspecs
在你开始把React Native植入到你的应用中之前,首先要决定具体整合的是React Native框架中的哪些部分。而这就是subspec要做的工作。在创建Podfile文件的时候,需要指定具体安装哪些React Native的依赖库。所指定的每一个库就称为一个subspec。
可用的subspec都列在node_modules/react-native/React.podspec中,基本都是按其功能命名的。一般来说你首先需要添加Core,这一subspec包含了必须的AppRegistry、StyleSheet、View以及其他的一些React Native核心库。如果你想使用React Native的Text库(即<Text>组件),那就需要添加RCTText的subspec。同理,Image需要加入RCTImage,等等。
6.2 Podfile
在React和React Native模块成功安装到node_modules目录之后,你就可以开始创建Podfile以便选择所需的组件安装到应用中。
创建Podfile的最简单的方式就是在iOS原生代码所在的目录中使用CocoaPods的init命令:(在Xcode项目目录中)
$ pod init
或者 $ touch Podfile
Podfile会创建在执行命令的目录中。你需要调整其内容以满足你的植入需求。下面是我调整后的Podfile的内容【这块有坑,出现和解决】:
# target的名字一般与你的项目名字相同
platform :ios, '9.0'
target 'NumberTileGame' do
# 'node_modules'目录一般位于根目录中
# 但是如果你的结构不同,那你就要根据实际路径修改下面的`:path`
pod 'React', :path => '../node_modules/react-native', :subspecs => [
'Core',
'RCTText',
'RCTNetwork',
'RCTWebSocket', # 这个模块是用于调试功能的
# 在这里继续添加你所需要的模块
]
# 如果你的RN版本 >= 0.42.0,请加入下面这行
pod "Yoga", :path => "../node_modules/react-native/ReactCommon/yoga"
end
6.3 安装Pod
Podfile写完了,现在就可以安装React Native的Pod包了:
$ pod install
然后你应该可以看到类似下面的输出(译注:同样由于众所周知的网络原因,pod install的过程在国内非常不顺利,请自行配备稳定的翻墙工具,或是尝试一些镜像源):
Analyzing dependencies
Fetching podspec for `React` from `../node_modules/react-native`
Downloading dependencies
Installing React (0.26.0)
Generating Pods project
Integrating client project
Sending stats
Pod installation complete! There are 3 dependencies from the Podfile and 1 total pod installed.
7. 代码集成
现在我们已经准备好了所有依赖,可以开始着手修改原生代码来把React Native真正植入到应用中了。在我们的2048示例中,首先尝试添加一个显示有"High Score"(得分排行榜)的React Native页面。
React Native组件
我们首先要写的是"High Score"(得分排行榜)的JavaScript端的代码。
创建一个index.ios.js文件
首先创建一个空的index.ios.js
文件。一般来说我们把它放置在项目根目录下。
index.ios.js
是React Native应用在iOS上的入口文件。而且它是不可或缺的!它可以是个很简单的文件,简单到可以只包含一行require/import
导入语句。本教程中为了简单示范,把全部的代码都写到了index.ios.js
里(当然实际开发中我们并不推荐这样做)。
在项目根目录执行以下命令创建文件:
$ touch index.ios.js
添加你自己的React Native代码
在index.ios.js中添加你自己的组件。这里我们只是简单的添加一个<Text>组件,然后用一个带有样式的<View>组件把它包起来。
'use strict';
import React from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
class RNHighScores extends React.Component {
render() {
var contents = this.props["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,
},
});
// 整体js模块的名称
AppRegistry.registerComponent('RNHighScores', () => RNHighScores);
RNHighScores
是整体js模块(即你所有的js代码)的名称。你在iOS原生代码中添加React Native视图时会用到这个名称。
8.集成RCTRootView
现在我们已经在index.ios.js
中创建了React Native组件,下一步就是把这个组件添加给一个新的或已有的ViewController。
简单起见:直接通过项目StoryBoard来创建一个按钮,并添加点击事件到ViewController了中。
Snip20170405_2.png9.事件处理
首先导入RCTRootView的头文件。
#import <React/RCTRootView.h>
【这块和中文网上有出入,中文网导入有误】
这里我们在btn的点击方法中添加如下代码
- (IBAction)highScoreButtonPressed:(id)sender {
NSLog(@"High Score Button Pressed");
NSURL *jsCodeLocation = [NSURL
URLWithString:@"http://localhost:8081/index.ios.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];
}
10. 调试前准备
现在基本的准备工作已经做完了,可以开始准备测试了。
修改App Transport Security
苹果默认不允许app访问不安全的http连接。这里我们通过在plist文件中添加如下key即可解决
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
运行Packager
From the root of your project, where the `node_modules` directory is located.
$ npm start
运行应用
如果你使用的是Xcode,那么照常编译和运行应用即可。如果你没有使用Xcode(但是你仍然必须安装Xcode),则可以在命令行中使用以下命令来运行应用:
在项目的根目录中执行:
$ react-native run-ios
运行效果
这个小程序中,你运行了之后点击 High Score
会出现如下页面,表示集成成功了
至此,就可以做功能的开发了。
网友评论