React Native 导入原生Xcode项目总结与记录

 

React Native 导入原生Xcode项目总结与记录

背景
最近学习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.开发环境准备

  1. 基础环境 首先要安装React Native在iOS平台上所需的一切依赖软件(如npm,node等) --- RN开发环境搭建传送门
  2. CocoaPods环境 cocoaPods是针对iOS和Mac开发的包管理工具,做过开发的并使用它管理过三方库的一点都不陌生,同样RN框架的代码也通过它来下载并添加到项目中。 ---- cocoaPods安装使用教程传送门

3.示例APP

示例程序采用2048小游戏,下面是尚未植入RN时候的页面

Snip20170405_1.png

4.依赖包

React Native的植入过程中需要React 和 React Native两个node依赖包。

package.json

具体的依赖包会记录在 package.json 文件中,如果项目中没有的自己创建吧(推荐使用 Sublime Text)

对于一个典型的RN项目来说,一般package.jsonindex.ios.js等文件会放在项目的根目录下。而iOS相关的源代码会放在一个名为 ios/ 的子目录中,这里同样放着Xcode项目文件(.xcodeproj

下面是我的package.json示例

示例中的version字段没有太大意义(除非你要把你的项目发布到npm仓库)。scripts中是用于启动packager服务的命令。dependencies中的react和react-native的版本取决于你的具体需求。一般来说我们推荐使用最新版本。你可以使用npm info reactnpm 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库(即组件),那就需要添加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的过程在国内非常不顺利,请自行配备稳定的FQ工具,或是尝试一些镜像源):

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中添加你自己的组件。这里我们只是简单的添加一个组件,然后用一个带有样式的组件把它包起来。

'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.png

9.事件处理

首先导入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会出现如下页面,表示集成成功了

Snip20170405_6.png

至此,就可以做功能的开发了。

posted @ 2017-04-05 14:21  xiaoyouPrince  阅读(5200)  评论(0编辑  收藏  举报