react native集成到原有的项目中(iOS)

接触RN也有一段时间了,基本上来说算是入门了,到目前RN的应用还没有达到期望的广泛度,大部分还是以原生+RN的方式进行混合开发,今天抽空写一下关于RN嵌入到iOS原生项目中的知识点。

前期准备

现在大部分嵌入方式都是采用cocoapods的方式引入RN依赖库到原生项目中,当然你也可以选择手动方式,不过很麻烦,本文采用的cocoapods来管理依赖。
RN所需要的环境也要装好,中文网有,具体我就不说了

集成

用Xcode创建一个项目,然后在项目中创建一个目录,把RN相关的都放在里面,如下图,我创建了一个js目录(这个目录你也可以放到iOS项目的根目录,任意)。

示例.png

然后cd到刚刚创建的js目录中,执行npm init,创建node环境,这时js目录中会多出一个package.json文件,这个文件和iOS中的Podfile类似,是用来记录着RN工程中要安装的依赖,目前你只需要关注dependencies这一项(把下面的内容覆盖到你生成的package.json文件中),该项中记录着RN项目要安装的依赖库。

{
  "name": "MixRNAndIOS",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "test": "jest"
  },
  "dependencies": {
    "react": "15.3.2",
    "react-native": "^0.36.1"
  },
  "jest": {
    "preset": "jest-react-native"
  },
  "devDependencies": {
    "babel-jest": "16.0.0",
    "babel-preset-react-native": "1.9.0",
    "jest": "16.0.2",
    "jest-react-native": "16.0.0",
    "react-test-renderer": "15.3.2"
  }
}

紧接着我们用npm包管理器来安装RN的依赖库,还是在js目录执行npm install,安装完毕之后,js目录会多出一个名为node_modules文件夹,RN所必须依赖的库都在这里面,然后我们创建一个index.ios.js作为RN项目的入口文件(名字可以任意起),然后我们就可以在入口文件中愉快的写RN代码了。

上面的步骤顺利执行完之后,RN项目已经完成了,现在我们要把RN集成到iOS原生项目中。

在项目根目录创建一个Podfile文件,如下所示,在项目的根目录执行pod install 来安装Podfile中指定的依赖库。

# The target name is most likely the name of your project.
target 'MixRNAndIOS' do

  # Your 'node_modules' directory is probably in the root of your project,
  # but if not, adjust the `:path` accordingly
  pod 'React', :path => ‘./MixRNAndIOS/js/node_modules/react-native', :subspecs => [
    'Core',
    'RCTText',
    'RCTNetwork',
    'RCTWebSocket', # needed for debugging
    # Add any other subspecs you want to use in your project
    'RCTImage',
  ]

end

注意:Podfile文件中的path路径
用pod安装完iOS所依赖的RN库之后我们就可以着手集成RN了。

RN为我们在iOS平台上提供了一个RCTRootView,RCTRootView是继承自iOS中UIView类,所以你可以像使用UIView一样使用RCTRootView,RN与iOS的交互都要在RCTRootView中进行,本篇文章先不讲交互的事,只讲集成,先把代码贴上,如下所示:

#import "ViewController.h"
#import "RCTRootView.h"


@interface ViewController ()

@property (nonatomic, strong) NSDictionary *props;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    self.props =   @{ @"param" : @[
                                @{
                                  @"name" : @"Alex",
                                  @"des": @"hello,我是从原生传递给RN界面的参数"
                                  }
                              ]
                      };
    
    
    UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake((self.view.bounds.size.width - 300)/2, 200, 300, 40)];
    [btn setTitle:@"点我进入react native界面" forState:UIControlStateNormal];
    [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    
    [btn addTarget:self action:@selector(highScoreButtonPressed) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
}

- (void)highScoreButtonPressed{
    NSURL *jsCodeLocation;
    
#ifdef DEBUG
    //开发的时候用,需要打开本地服务器
    jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios"];
#else
    //发布APP的时候用
    jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"index.ios" withExtension:@"jsbundle"];
#endif
    
    RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL : jsCodeLocation
                                                 moduleName        : @"RNHighScores"
                                                 initialProperties : self.props  //将native数据传送到RN中
                                                 launchOptions     : nil];
    
    rootView.frame = [UIScreen mainScreen].bounds;
    UIViewController *vc = [[UIViewController alloc] init];
    vc.view.backgroundColor = [UIColor redColor];
    [vc.view addSubview:rootView];
    [self presentViewController:vc animated:YES completion:nil];
}

创建RCTRootView,将RCTRootView添加到VC中的view上就OK了
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"index.ios" withExtension:@"jsbundle"];
这一行你先忽略,后面会说。
然后cd到js目录,执行react-native start或者执行npm start,来启动本地node服务器,如果没有错误的话我们就只需最后一步了,用Xcode打开项目,运行项目,大功告成。

打RN离线包

此时我们的项目是依赖于刚刚启动的本地服务器的,要是上线怎么办,所以我们需要打个RN离线包,这样就可以摆脱本地服务器了。
进入js目录,创建一个bundle目录,这里面存放打包后的RN资源,包括RN代码和图片等静态资源,在js目录里执行下面的打包命令,

react-native bundle --entry-file ./index.ios.js --bundle-output ./bundle/index.ios.jsbundle --platform ios --assets-dest ./bundle --dev false

如果成功的话,在bundle目录下会生成存放RN静态资源的assert目录和RN的index.ios.jsbundle代码文件,将这俩家伙拖进Xcode中

拖.png

注意:要以引用的方式拖进Xcode中。

在文章的集成部分我粘贴了一大段代码,源代码中有两句代码用来生成RN资源的URL,第一句是依赖本地服务器的,一般调试RN代码时用,第二句是引入打包后的RN资源的URL,发布APP的时候用的,我用宏来进行控制。

jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"index.ios" withExtension:@"jsbundle"];

注意:假如我们把第一种获取URL的方式注释掉,宏也注释掉,如果iOS项目是DEBUG模式,而我们加载的明明是RN的离线包,你会发现从原生页面跳转到RN页面的时候,顶部的statusBar会有加载资源的进度显示,不要纠结,运行项目的时候改成release模式就好了,来张效果图。

友情提示,在RN中想引入iOS中Assets.xcassets里面的图片的话可以直接写图片的文件名,如下面这样。

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

推荐阅读更多精彩内容