iOS原生项目集成ReactNative(持续更新)

前言

最近发现很多app都使用了ReactNative这门火热的技术,不禁虎躯一震,因为公司的工作相对安逸,自己一直打算学习一下,但每次都不了了之,这次又默默看了看招聘信息,RN已经势不可挡,新的一年想升职加薪看来要努力啦!
下面进入我们的主题,在iOS原生项目中集成ReactNative,鼓捣了一天终于成功了,鉴于市面上的资料都有些老旧了,所以我将我的经验分享给大家,赶紧上车,落后就要挨打。

tips:如果操作过程中碰到什么错误或问题,请到文章最后问题合集中查看是否有解决办法

一、准备工作

本文使用的版本
"react": "16.0.0",
"react-native": "0.51.0"

1、搭建开发环境

如果你已经创建过RN项目,并且运行成功了,那么你的环境配置肯定是没有问题的,但是如果你是第一次进行学习,那么就要搭建开发环境了,具体的可以参考搭建ReactNative开发环境,搭建好后你可以按照他的提示创建一个RN项目运行一下,看环境是否成功

2、安装CocoaPods

CocoaPods相信每一个iOS开发者都有接触吧,如果你没有使用过也没关系,参考CocoaPods的安装使用和常见问题这篇文章学习下吧。
本文只提供CocoaPods安装React Native的方式,这个简单易用。
这里就不提供手动集成的办法了,因为笔者也没尝试过,如果有需要可以自己查资料。

二、集成ReactNative

1、文件配置

1)创建存放文件夹RNComponent和配置文件package.json

在项目中创建文件夹RNComponent并创建package.json配置文件,文件夹名字可以自定义,主要用来存放RN相关的文件,如下图

//package.json 终端创建方法
$ cd 需要放置的目录下(项目的根目录/项目中自己创建的文件夹)
$ touch package.json
文件目录.png

package.josn 中的内容如下,其中name位App的名字,dependencies为react和react-native的版本,在创建这些信息时,建议利用react-native init AwesomeProject新建新项目时会自动创建package.json,直接把文件复制过来,更改name为自己的原生项目名,确保信息为最新的,且不容易出错。

{
  "name": "RNExample",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "test": "jest"
  },
  "dependencies": {
    "react": "16.0.0",
    "react-native": "0.51.0"
  },
  "devDependencies": {
    "babel-jest": "22.0.4",
    "babel-preset-react-native": "4.0.0",
    "jest": "22.0.4",
    "react-test-renderer": "16.0.0"
  },
  "jest": {
    "preset": "react-native"
  }
}

2)安装React Native依赖包

进入到RNComponent文件夹下运行命令行

npm install

执行结束后项目中会多出一个node_modules文件夹。

执行指令.png
执行结果png

看到有的文章说这里执行起来很慢,但是我这里很快,图中看见27.596s,可能是因为我在配置环境的时候使用了淘宝镜像,建议大家也这么做,搭建ReactNative开发环境里面有方法。

2、创建入口文件index.ios.js

终端创建方法

$ cd 需要放置的目录下(项目的根目录/项目中自己创建的文件夹)
$ touch index.ios.js
image.png

我这里开发使用的工具是WebStorm,这里可以分享下我的下载地址

index.ios.js 代码如下

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View
} from 'react-native';

class RNExample extends Component {
    render() {
        return (
            <View style={styles.container}>
                <Text style={styles.welcome}>
                    Welcome to React Native!
                </Text>
                <Text style={styles.instructions}>
                    To get started, edit index.ios.js
                </Text>
                <Text style={styles.instructions}>
                    Press Cmd+R to reload,{'\n'}
                    Cmd+D or shake for dev menu
                </Text>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
    },
});
// 注册组件,程序入口
// 第一个参数:注册模块名称,这里亲测不和项目名一致也可以,但是好多资料说名字要和项目名一致
// 第二个参数:函数,此函数返回组件类名,程序启动就会自动去加载这个组件
AppRegistry.registerComponent('App', () => RNExample);

3. Cocoapods集成React Native

如果还没有使用CocoaPods

$ cd 项目的根目录
$ touch Podfile
$ open -e Podfile
$ pod install //只是注释,在内容添加保存后执行
image.png

Podfile中添加的内容,添加后保存,然后执行 pod install

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, ‘9.0’
use_frameworks!

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

end

注:上面添加的有注释的几个都是查找多处资料找到的,好多老的资料都不可行了

执行结果:


image.png

三、项目处理

1、打开项目

使用CocoaPods后需要用箭头所示文件打开


image.png

2、添加RCTRootView

这里只是在ViewController中进行了测试,具体放在什么地方,怎么放置大家根据项目需求而定

#import "ViewController.h"
#import <React/RCTRootView.h>
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
    button.center = self.view.center;
    [button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    [button setTitle:@"Hello" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)buttonAction{
    NSString * strUrl = @"http://localhost:8081/index.ios.bundle?platform=ios&dev=true";
    NSURL * jsCodeLocation = [NSURL URLWithString:strUrl];
    
    RCTRootView * rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                         moduleName:@"App"
                                                  initialProperties:nil
                                                      launchOptions:nil];
    self.view = rootView;
}

@end

3、配置App Transport Security

在iOS 9以上的系统中,除非明确指明,否则应用无法通过http协议连接到localhost主机。 建议在Info.plist进行如下设置,否则会报Could not connect to development server错误


image.png

4、开启服务器

在运行我们的项目之前,我们需要先启动我们的开发服务器。进入 RNComponent目录 ,然后命令行启动服务:

react-native start

5、运行程序

我这里是用Xcode运行的项目,指令没有运行起来,很尴尬。
项目跑起来,very good😄,这里只是在模拟器上运行,真机上运行请见问题合集2

image.png

之前一直报错无法连接服务器,现在我觉得问题就是没有执行第四部开启服务器,如果有什么问题请留言交流,下面有个问题集合,我以后遇到的问题都会收集起来,希望对大家有所帮助,共同进步。

6、吃水不忘挖井人

参考链接:
https://www.jianshu.com/p/3dc9d70a790f
https://reactnative.cn/docs/0.42/getting-started.html
https://www.jianshu.com/p/47174bf215bf

四、问题集合

问题都是我在开发中遇到的,情况不同解决方法可能不同仅供参考

1、'fishhook/fishhook.h' file not found

image.png

解决办法:将#import <fishhook/fishhook.h> 改为 #import "fishhook.h"即可

2、Could not connect to development server

如果正常的话http://localhost:8081/index.ios.bundle?platform=ios&dev=true将会有内容
解决办法:

  • 1、是否配置App Transport Security
  • 2、是否开启服务器,执行react-native start
  • 3、真机上运行报错
    如果模拟器上是可以的而在真机上运行报上面的错误请按下面步骤执行,
    打开设置-网络-查看当前ip地址,将项目中的localhost改为当前ip(注意,手机的wifi应当和电脑的wifi是同一个才可以)


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

推荐阅读更多精彩内容