爽爆天ReactNative基础篇 - 2.2 搭建iOS工程

开始本章之前,仍然不厌其烦地啰嗦几句,本章节基于苹果的mac OS X 系统,本系列教程的所有文章也都是基于此系统的,本人强烈建议使用mac进行开发。

本章概述(react-native下文有时会简称 rn):

  • 【环境】我们一开始会先检查下需要安装与配置的环境是否OK。
  • 【构建项目】然后我们会构建一个iOS项目,如果已有项目我们会调整下结构。
  • 【安装iOS依赖库】为了建立iOS与react-native的连接,我们要在iOS项目中安装rn相关的依赖库。
  • 【给iOS添加rn相关代码】给iOS项目添加 rn 代码,增加rn支持。
  • 【给rn项目添加rn代码】给rn项目添加rn代码
  • 【运行看效果】以本地服务和打包的形式看iOS应用最终效果。

1 本章示例代码

1
https://github.com/luochenxun/react-native-happy-learn.git 分支名: chapter2.2

你可以这样拉下来:找个目录,然后敲

1
2
3
git clone -b chapter2.2 https://github.com/luochenxun/react-native-happy-learn.git rnProject
进入 rn 目录,执行 `npm install`
进入 iOS 目录,执行 `pod install`

2 基础环境

2.1 安装 Xcode , cocopads

参见环境配置一章

2.2 建立现有iOS项目(如果你已有iOS项目,此步聚可以跳过)

在硬盘上找个地方放置我们的工程,比如 rnDemo。

然后在里面分别创建 iOS,Android,rn三个目录,就像这样:

1
2
3
4
rnDemo // 项目根目录
├── Android // 存放安卓项目代码
├── iOS // 存放 iOS项目代码
└── rn // 存放 react-native 代码

因为这节我们主要是建立iOS工程,所以我们使用Xcode,新建一个工程到iOS目录中。

1
2
3
进入Xcode,在 File -> new project... -> Single view application

如下图:

Xcode新建项目

创建成功后会在iOS目录中多出一个以项目名称为命名的项目目录。把目录中的文件都挪到上层iOS目录中。使iOS目录为项目的根目录。

2.3 安装 react-native

使用命令行进入 rn 目录,运行 npm init 根据系统问的关于项目的问题回答之,便建立好了一个nodeJS项目,可以看到目录里多了一个package.json文件。

然后执行

1
2
npm install -s react
npm install -s react-native

关于nodeJS的内容,可以参考后面关于NodeJS的介绍。这里你只要知道一个react-native工程,其实就是一个NodeJS工程。NodeJS是JavaScript的运行时环境,提供JS的本地编译运行与打包等功能。而npm提供了NodeJS的依赖库管理,这就体现在package.json文件中,这个json文件记录了本NodeJS项目的信息,依赖库信息等。

我们看看最后生成的两个文件 package.json & node_modules

  • node_modules

node_modules是 NodeJS放依赖库的地方,我们下下来的 react-native库及他所依赖的库都放在 node_modules里面。每个库就是一个module,放在一个独立的文件夹里面。

  • package.json

这个上面介绍过了。 我们修改下pakcage.json让他变成这样(正式使用时,注释要去掉):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"name": "MyRnDemo", # 项目名
"version": "1.0.0", # 项目版本号
"description": "My First react-native demo", # 项目描述
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start" # 项目运行的脚本
},
"dependencies": { # 本RN项目的依赖库,可以看到,这里依赖了 react 与 react-native
"react": "^0.14.8",
"react-native": "^0.25.1"
},
"author": "luochenxun",
"license": "ISC"
}

其实有了这个package.json文件后,我们他日要升级 react-native 或是要添加其它库时,只要添加或修改到 dependencies内,然后把node_modules删之,最后在根目录直接运行 npm install 就行,npm会根据package.json中的依赖库信息,安装项目所有需要的依赖库。

3 安装iOS依赖库

我们使用 cocoapods 来安装。

cocoapods 是iOS的依赖库管理工具,就像 npm之于NodeJS一样,它可以让我们非常方便地安装iOS项目需要使用到的第三方库。

首先进入iOS项目,执行

1
pod init  # 初始化cocoapods,主要是创建一个Podfile,这个文件如同 package.json,是cocoapods的依赖库配置文件

然后我们修改生成的 Podfile,使之像下面一样(同样,注释只是我为了说明,不用复制到项目中):

1
target 'rnDemo' do   # target为你这个iOS项目的名称,如果是新建的项目,就是你new project时输入的名称
  • 1 下面这部分是重点,它指定了依赖的本地 react-native库路径,和所依赖的子库,安装时,它会到这个目录中找所需要的文件。 pod ‘React’, :path => ‘../rn/node_modules/react-native’, :subspecs => [

    1
    2
    3
    4
    5
    'Core',
    'RCTImage',
    'RCTNetwork',
    'RCTText',
    'RCTWebSocket',
  • 2 Add any other subspecs you want to use in your project ]

    end

最后在iOS项目根目录执行 pod install

会在本地生成一个 rnDemo.xcworkspace 文件,执行它,就可以打开iOS工程了。

4 给iOS添加rn相关代码

4.1 添加 ReactView

将我们示例代码中的 ReactView文件夹拖入项目,ReactView是一个封装了加载rn模块的View

主要代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*!
* 加载指定的 rn 模块,将之生成特定的 View
*/
- (instancetype)initWithFrame:(CGRect)frame
withModuleName:(NSString *)jsModuleName
initialProperties:(NSDictionary *)initialProperties {

self = [super initWithFrame:frame];
if (self) {

// 使用本地服务器提供的Bundle
NSURL *jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle"];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:jsModuleName
initialProperties:initialProperties
launchOptions:nil];

[self addSubview:rootView];
rootView.frame = self.bounds;
rootView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}

return self;
}

修改项目中的 ViewController.m,添加代码加载rn模块,并将 加载成功后的 ReactView装进 ViewController中:

1
2
3
4
5
6
- (void)viewDidLoad {
[super viewDidLoad];

ReactView *rnView = [[ReactView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height) withModuleName:@"RnDemo" initialProperties:nil];
self.view = rnView;
}

4.2 添加 rn 相关代码

在rn目录,新建 index.ios.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
28
29
30
31
32
33
34
35
36
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';

class RnDemo extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
欢迎来到加油宝!
</Text>
</View>
);
}
}

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
}
});

// 导出rn模块,注意 rn 模块名要与 iOS 中 ViewController内指定的模块名相同!
AppRegistry.registerComponent('RnDemo', () => RnDemo);

5 启动rn

在终端进入rn目录,输入 npm start 开启本地服务

在Xcode中运行项目, 按 cmd+r 刷新,就可以看到我们的欢迎界面啦~ 至此,将rn集成入iOS项目便OK了。保存这个项目后续我们用rn开发就可以不写一句iOS代码,构建iOS应用了!!

6 将RN打包成jsbundle

当我们应用想运行在手机上,或者是不想用本地服务时,我们可以将rn打成包装进app,只要运行下面的打包命令就OK了。

打包命令

1
react-native bundle --minify --entry-file ./index.ios.js --bundle-output ./main.jsbundle --platform ios

–minify 压缩

–entry-file 入口JS

–bundle-output 输入生成的JSbundle

–platform 平台

运行完命令后,本地会生成 main.jsbundle,将它拖入Xcode项目,对 ReactView作些修改:

1
2
将生成 jsCodeLocation 的那一句改成这样:
NSURL *jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];

改用本地JSBundle

然后运行项目,就可以不需要本地服务器运行iOS rn项目了~~ :)

7 本章示例代码

1
https://github.com/luochenxun/react-native-happy-learn.git 分支名: chapter2.2

你可以这样拉下来:找个目录,然后敲

1
2
3
git clone -b chapter2.2 https://github.com/luochenxun/react-native-happy-learn.git rnProject
进入 rn 目录,执行 `npm install`
进入 iOS 目录,执行 `pod install`