RN开发过渡 - 在纯原生iOS项目中集成React-Native

RN 入门

本文主要记录了自己在往原生项目中集成React-Native(以下简称RN)开发的一些经验和踩的坑,对这次的经历做一个备忘录,同时希望能帮到更多的人。

关于为什么要使用RN开发,本文不做更多的论述。RN的优缺点的论点网上太多了,读者自行搜索查找、思考、甄别。

目前RN的最新版本是051,本文所有的内容都在该版本上的开发、测试。

我本人使用的是Mac端开发,并只在iOS的项目上做的测试。

好,进入正题。

一、搭建RN开发环境

既然要使用RN开发,最基本的肯定要搭建其开发环境。搭建RN开发环境一共分为:

  • 安装必要软件
  • 测试安装

1. 安装必需的软件

Homebrew

Homebrew, Mac系统的包管理器,用于安装NodeJS和一些其他必需的工具软件。

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

在Max OS X 10.11(El Capitan)版本中,homebrew在安装软件时可能会碰到/usr/local目录不可写的权限问题。可以使用下面的命令修复:

sudo chown -R `whoami` /usr/local
Node

使用Homebrew来安装Node.js.

React Native目前需要NodeJS 5.0或更高版本。本文发布时Homebrew默认安装的是最新版本,一般都满足要求。

brew install node

安装完node后建议设置npm镜像以加速后面的过程(或使用科学上网工具)。注意:不要使用cnpm!cnpm安装的模块路径比较奇怪,packager不能正常识别!

npm config set registry https://registry.npm.taobao.org --global

npm config set disturl https://npm.taobao.org/dist --global
Yarn、React Native的命令行工具(react-native-cli)

Yarn是Facebook提供的替代npm的工具,可以加速node模块的下载。React Native的命令行工具用于执行创建、初始化、更新项目、运行打包服务(packager)等任务。

npm install -g yarn react-native-cli

安装完yarn后同理也要设置镜像源:

yarn config set registry https://registry.npm.taobao.org --global

yarn config set disturl https://npm.taobao.org/dist --global

如果你看到EACCES: permission denied这样的权限报错,那么请参照上文的homebrew译注,修复/usr/local目录的所有权:

sudo chown -R `whoami` /usr/local

安装完yarn之后就可以用yarn代替npm了,例如用yarn代替npm install命令,用yarn add 某第三方库名代替npm install --save 某第三方库名

Watchman

Watchman是由Facebook提供的监视文件系统变更的工具。安装此工具可以提高开发时的性能(packager可以快速捕捉文件的变化从而实现实时刷新)。

brew install watchman
Xcode

这个就不多说了,在APPStrore下载即可。最好保证下载Xcode7.0以上。

2.测试

以上软件安装好了之后,我们现在可以开始尝试创建一个RN项目了,测试看是否出现纰漏。
打开Mac的终端工具命令行:

react-native init myFirstRNProject

这里是在mac的根目录创建一个myFirstRNProject的文件夹。我们的项目所需要的一切文件也会在这个文件夹里面被创建好。这种方式创建的就是最新版本的RN,也就是0.51版本。
如果我们需要进行指定版本的创建的话,可以像下面这样创建:

react-native init myFirstRNProject --version 0.45

这种方式将会创建0.45版本的RN项目。
创建RN文件夹后,执行:

cd myFirstRNProject

进入到该项目中。

react-native run-ios

启动项目中的iOS部分。
注意: 启动之后,Mac会自动开启一个终端的对话框,这个对话框在项目的开启期间必须要一直打开着,如果被关闭,整个项目也就被关闭了。
打开项目看到这个样子:

RN新项目

我们将在 APP.JS文件夹中编写项目需要的代码。 如果是049之前的版本,则应该在 index.ios.jsindex.Android.js中分别iOS和安卓的代码。
如果一切正常,说明项目就是创建成功了。

二、搭建原生项目集成环境

搭建好了开发环境之后,我们能够随时创建一个新的项目了。这时候就具备了给原生项目集成RN的环境。

1. 首先创建一个空的文件夹。

这个文件夹将会是集成之后项目文件。假设我给他取名: iOS-RN.

2. 在 iOS-RN 文件夹中,创建一个/ios文件。

这个/ios文件中将存放原生项目中所有的文件。这直接将原生项目中的文件复制一份拷贝过来即可。

3. 安装JavaScript依赖包: package.js文件

在项目根目录(和/ios平级)下创建一个名为package.json的空文本文件,然后填入以下内容:

{
  "name": "MyReactNativeApp",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start"
  },
  "dependencies": {
    "react": "16.0.0-alpha.6",    //  指定了React 版本
    "react-native": "0.51"    //这里指定了RN的版本
  }
}

示例中的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@某.某.某版本。如果你使用多个第三方依赖,可能这些第三方各自要求的react版本有所冲突,此时应优先满足react-native所需要的react版本。其他第三方能用则用,不能用则只能考虑选择其他库。

设置完成之后,安装依赖包:

$ npm install
4. 在原生项目中使用CocoaPod添加RN依赖文件

使用终端cd进入到/ios文件中,安装CocoaPod依赖包管理系统。(这里推荐使用CocoaPods,如果之前的原生项目中没有安装的话,需要自行想办法安装一个)。
对于已经安装了CocoaPod 的项目,我们进入到对应的podfile文件:

$ vim podfile

在podfile文件中添加以下内容:

 # 'node_modules'目录一般位于根目录中
  # 但是如果你的结构不同,那你就要根据实际路径修改下面的`:path`
  pod 'React', :path => '../node_modules/react-native', :subspecs => [
    'Core',
    'CxxBridge', # 如果RN版本 >= 0.45则加入此行
    'DevSupport', # 如果RN版本 >= 0.43,则需要加入此行才能开启开发者菜单
    'RCTText',
    'RCTNetwork',
    'RCTWebSocket', # 这个模块是用于调试功能的
    # 在这里继续添加你所需要的RN模块
  ]
  # 如果你的RN版本 >= 0.42.0,则加入下面这行。
  pod "yoga", :path => "../node_modules/react-native/ReactCommon/yoga"
 # 这里注意: 如果是0.49以下的RN,则使用下面这条:
 # pod "Yoga", :path => "../node_modules/react-native/ReactCommon/yoga"

   # 如果RN版本 >= 0.45则加入下面三个第三方编译依赖
  pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
  pod 'GLog', :podspec => '../node_modules/react-native/third-party-podspecs/GLog.podspec'
  pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'

完了之后,更新Pod。

 $ pod install   

有时候会更新失败,注意查看失败的原因,对症修改即可。
更新成功之后,我们在项目中就可以通过import React使用React提供的库文件了。在每一个需要用到RN相关内容的界面的原生代码中,都需要加入这个头文件。

三、桥接RN和iOS项目中的内容

按照传统,我打算使用RN写一个“Heollo world” 的界面,然后在原生的项目中使用这个界面。

1. 创建index.js文件。

在和ios文件夹平级的目录下(根目录),使用命令
$ touch index.js
创建index.js文件。这个文件是RN的入口文件,如果是 049之前的RN,那么应该创建index.ios.js文件。

2. 在index.js文件写入以下代码:
import React from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native';

class FirstView extends React.Component {
  render() {
    var contents = this.props.rootTag;
    return (
      <View style={styles.center}>
        <Text >
          {this.props.content}
        </Text>
      </View>

    );
  }
}

const styles = StyleSheet.create({
  center: {
    marginTop: 50,
    width:120,
    height: 60,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor:"red"
  },
});

// 整体js模块的名称
AppRegistry.registerComponent('FirstView', () => FirstView);

具体代码的意思就是在一个页面中添加了一个包含“Hello world”文字的 <Text>控件。

3. 编写原生代码对接RN

为了简单起见,我直接在AppDelegate文件中,将window的根视图设置成RN编写的“Hello world”界面。
当然,我们同样可以在其他的原生界面进行跳转到RN界面。
首先

import  React

然后在 didFinishLaunchingWithOptions 函数中:

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        self.window = UIWindow.init(frame: CGRect.init(x: 0, y: 0, width: ScreenWidth, height: ScreenHeight))
        self.window?.makeKeyAndVisible()

//      如果是 使用真机调试,需要使用电脑的IP地址。
//      let url = URL.init(with: "http://192.168.0.174:8081/index.bundle?platform=ios")   

//     如果是使用Xcode自带的模拟器,则直接使用本地服务器的端口即可。
        let url = URL.init(with: "http://localhost:8081/index.bundle?platform=ios")
        let rootView = RCTRootView.init(bundleURL: url, moduleName: "FirstView", initialProperties: [ "content":"Hello world"], launchOptions: nil)
        let VC = UIViewController.init()
        VC.view = rootView
        self.window?.rootViewController = VC
        return true
    }

注意: 这里的FirstView 的名称必须和RN中注册的名称一模一样。不然会无法识别的。
这段代码的意思就是从RN中加载一个页面(这个页面就是我们写的“Hello world”页面),然后作为window的根视图展示。

4. 启动RN项目

使用mac的终端工具,cd 进入到项目的根目录,就是上面说的 iOS-RN文件夹,在这里可以看到 index.js文件。
输入命令行:

$ npm start  

之后,RN项目开始启动,最后, 终端框中会看到这句提示:Loading dependency graph, done.,说明RN启动完成。这时候注意,不要关闭这个终端,如果需要使用终端执行其他的命令,可以新建窗口。
这时候所有的RN依赖库都加载完毕,等待原生项目启动调用。

5. 启动原生项目

Xocde中,选择模拟器,comand+R。

如果一切正常的话,打开模拟器之后,会直接进入到了“Hello world”界面。
下图:


hello world

以上就是在原生项目中集成RN的全部过程了。当然这个过程的步骤很多,很有可能出现各种各样的错误,这时候需要耐心仔细看错误提示。RN的错误提示做的还是很成熟的,我自己接入RN以来各种错误大部分都是通过其错误提示修复的,实在不行,就上各种搜索引擎上去搜索吧。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容