将 React Native 集成至现有的 iOS 项目中

React Native 的原理

请大家直接参看React Native 从入门到原理 - 简书,这篇文章简明扼要的讲了 react-native 是在怎样的愿景下产生的,以及 react-native 在 iOS 中运行的基本原理

集成至现有的 iOS 项目中

主要参考 Integration With Existing Apps 即可,其基本逻辑为:

  1. 使用 npm 获取 react-native 及其依赖的 react 相关资源文件
  2. 用 Cocoapods 读取处于 npm 管理的 node_modules/react-native/ 文件夹下的 React.podspec,并根据 podspec 来集成 react-native 至 iOS 项目中
  3. 在 iOS 代码中创建 RCTRootView 并将其添加到任意 UIView 上予以展示即可

下面的几点大家可能需要注意一下:

  • 官方的这个页面已经很久不更新了,其 package.json 中的 react 和 react-native 版本都不是最新的,推荐大家直接使用 npm install --save react react-native 来安装
  • 如果 node_modulesyour_project.xcodeproj 处于同一文件夹下,Xcode 在编译时有可能报出 Argument list too long: recursive header expansion failed at XXXX 错误,所以我建议大家在将 react-native 集成进已有项目时使用如下目录结构。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    ├── index.ios.js
    ├── ios
    │   ├── Podfile
    │   ├── Podfile.lock
    │   ├── Pods
    │   ├── your_project
    │   ├── your_project.xcodeproj
    │   └── your_project.xcworkspace
    ├── node_modules
    │   ├── react
    │   ├── react-native
    │   ...
    └── package.json

使用

这里我就说一下学习使用过程中值得注意的地方

live-reload

这是我非常喜欢的一个 react-native 开发时的特性,在模拟器下直接 ⌘+D 打开开发者菜单,选择 Enable Live Reload 即可,可以很大程度上提高开发效率。

下面是 react-native 官网对这个特性的描述

Don’t Waste Time Recompiling

React Native lets you build your app faster. Instead of recompiling, you can reload your app instantly. With hot reloading, you can even run new code while retaining your application state. Give it a try - it’s a magical experience.

官方博客

iOS 调用原生代码

请直接看这里 Native Modules iOS

核心步骤其实就是:

  1. 在 ObjC class imp 中加入 RCT_EXPORT_MODULE()
  2. 要暴露给 react-native 的方法写为 RCT_EXPORT_METHOD() 所要求的形式
  3. react-native 中 import { NativeModules } from 'react-native'
  4. 使用 NativeModules.YOUR_CLASS.YOUR_METHOD(params)

网络请求

官方页面中已经对 react-native 的基本网络请求格式进行了说明。但是面对已有的 iOS 项目,可能对已有项目中的 NetworkManger 做一个到 react-native 的桥接是最好的方式了

布局

react-native 的布局方式为前端传统的盒子模型 + flex

样式

The style names and values usually match how CSS works on the web, except names are written using camel casing, e.g backgroundColor rather than background-color.

(react-native 中)样式名称和值通常和在 web 页面上工作的 CSS 相匹配,不同的是样式名称使用驼峰命名法,比如 backgroundColor 对应 background-color

数据

react-native 组件间的数据传递和 iOS native code 有很大的不同,它直接使用了 react 的数据传递机制,官网上对其有详细的说明

Prop

不可变的值,在组件初始化时设定,设定方式如下:

1
<Component Prop1=Value1 Prop2=Value2></Component>

State

可变值,调用 setState 后,该组件的 render 会被重新调用,以根据 state 控制 UI

UI 组件

rn 提供了非常多的 UI 组件,我个人认为还是先简要浏览一遍各个组件,下载一下官方的 UIExplorer 运行一下,等真正开发的时候再仔细钻研每个组件使用方式

发布

打包发布至 AppStore 时,我们需要在 Xcode > Build Phases 中添加 Run Script Phase:

1
2
export NODE_BINARY=node
../node_modules/react-native/packager/react-native-xcode.sh

通过执行脚本 node_modules/react-native 中的脚本,将 index.ios.js 以及其他 js 文件编译成 main.jsbundle

在 release 环境下运行的 App, react-native 默认会读取 bundle 中的 main.jsbundle 而非开发时由 node 动态编译的 index.ios.js 及其他资源文件

热更新

上面讲到的发布中 react-native 默认读取 bundle 中的 main.jsbundle,而 react-native 热更新的原理就是让 react-native 热更新插件从服务器读取最新的 main.jsbundle 并交由 react-native 解析执行

这里我直接使用了 Code Push,其官方的新手教程已经非常详尽了,我在这里也就不再赘述

值得注意的一点是,发布到正式环境的命令为:

1
code-push release-react YOUR_APP_NAME ios --plistFile YOUR_APP_FOLDER_PATH/Info.plist --deploymentName Production --mandatory true

另外附上我集成 Code-Push 并成功对其进行测试的 demo

使用 react native 的优劣

我个人认为 react-native 有如下的特点

优点

  • 适合 Web 人员入手
  • 部分页面可以重用
    • 有一些 web 开发中比较先进的理念

缺点

  • 原生应用开发者入手难度大
  • 项目架构更加复杂

参考资料