在iOS項目中集成React-Native并交互

需求

在公司原有的項目中想使用RN,但羅馬不是一天建成的,沒辦法把所有代碼全部換成RN,而且原來的項目功能比較多,我不認(rèn)為全部換成RN就是好的,所以準(zhǔn)備將項目中的一些合適用于RN的頁面先轉(zhuǎn)變過來,這篇文章就是在iOS項目中集成RN的步驟。和一些簡單的交互。
效果圖


Demo.gif
我寫了一個簡單的項目更新到了github上,希望和大家更好的交流https://github.com/gjjggg/iOSRN.git

前提

1電腦已經(jīng)安裝過react-native相關(guān)環(huán)境
2電腦已經(jīng)安裝過Cocoapods(官方推薦的辦法,如果想在項目中使用Cocoapods可以找一下唐巧寫的安裝教程)

步驟

  1. 創(chuàng)建:首先我們先創(chuàng)建一個iOS項目,我命名為iOS-RN;
  2. package.json:我們把具體的依賴包記錄在package.json文件中。如果項目根目錄中沒有這個文件,那就自己創(chuàng)建一個。用于初始化react-native。 (對于一個典型的React Native項目來說,一般package.json和index.ios.js等文件會放在項目的根目錄下。而iOS相關(guān)的原生代碼會放在一個名為ios/的子目錄中,這里也同時放著你的Xcode項目文件(.xcodeproj)。(放置位置如圖))
屏幕快照 2017-07-10 下午1.54.11.png

package.json內(nèi)容如圖

屏幕快照 2017-07-10 下午2.08.05.png
{
//name對應(yīng)著項目得名字
  "name": "iOS-RN",
  //version字段沒有太大的意義
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start"
  },
  "dependencies": {
    //react 版本號
    "react": "16.0.0-alpha.6",
    //react-native  版本號 (react和react-native要對應(yīng) 這里我建議用相對穩(wěn)定的版本 這里我用的0.44.3)
    "react-native": "0.44.3"
  }
}

package.json配置好咱們就安裝依賴包
使用終端安裝 $ npm install一下( 在包含有package.json文件的目錄(一般也就是項目根目錄)中運行下列命令來安裝)

Last login: Mon Jul 10 14:16:51 on ttys001
guohongandeiMac-2:~ guohongan$ cd /Users/guohongan/Desktop/iOS-RN 
guohongandeiMac-2:iOS-RN guohongan$ npm install

如果報錯看一下package.json里的name是不是和項目名對應(yīng),react和react-native版本是否對應(yīng)

3.React Native框架:React Native框架整體是作為node模塊安裝到項目中的。下一步我們需要在CocoaPods的Podfile中指定我們所需要使用的組件。
首先我們在項目的根目錄 $ pod init (創(chuàng)建Podfile)

屏幕快照 2017-07-10 下午2.44.29.png

根目錄就會多一個Podfile

屏幕快照 2017-07-10 下午2.45.16.png

下一步$ vim Podfile (打開Podfile文件) 點 ‘e’ 進(jìn)入編輯e
我們在里面寫這幾句話 點 ‘esc’ 然后輸入‘:’'w''q'保存退出編輯

屏幕快照 2017-07-10 下午2.48.54.png
// 9.0 最低兼容到多少
platform :ios, ‘9.0’ 
//iOS-RN 項目得名字
target 'iOS-RN' do 
 // 'node_modules'目錄一般位于根目錄中
 // 但是如果你的結(jié)構(gòu)不同,那你就要根據(jù)實際路徑修改下面的`:path`
 // './node_modules/react-native' 這個路徑是根據(jù)Podfile的位置
pod 'React', :path => './node_modules/react-native', :subspecs => [
    'Core',
    'DevSupport', //如果RN版本 >= 0.43,則需要加入此行才能開啟開發(fā)者菜單
    'RCTText',
    'RCTNetwork',
    'RCTWebSocket'
      // 在這里繼續(xù)添加你所需要的模塊
  ]
   // 如果你的RN版本 >= 0.42.0,請加入下面這行
   // './node_modules/react-native/ReactCommon/yoga' 這個路徑是根據(jù)  Podfile的位置
pod "Yoga", :path => "./node_modules/react-native/ReactCommon/yoga"

end

創(chuàng)建好了Podfile后,就可以開始安裝React Native的pod包了。$ pod install
install 成功以后的根目錄如圖所示

屏幕快照 2017-07-10 下午3.00.03.png

現(xiàn)在我們已經(jīng)準(zhǔn)備好了所有依賴,可以開始著手修改原生代碼來把React Native真正植入到應(yīng)用中了
—————————————————————————————————————————————————————

接下來我們來在iOS中創(chuàng)建原生界面

創(chuàng)建一個index.ios.js文件:首先創(chuàng)建一個空的index.ios.js文件。一般來說我們把它放置在項目根目錄下。(index.ios.js是React Native應(yīng)用在iOS上的入口文件。而且它是不可或缺的)(為了簡單示范,把全部的代碼都寫到了index.ios.js里 實際開發(fā)中不推薦)

# 在項目根目錄執(zhí)行以下命令創(chuàng)建文件:
$ touch index.ios.js

然后用WebStorm來打開整個項目
在index.ios.js里

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

export default class iOSRN 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.android.js
                </Text>
                <Text style={styles.instructions}>
                    Double tap R on your keyboard to reload,{'\n'}
                    Shake or press menu button 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('iOSRN', () => iOSRN);

在iOS項目創(chuàng)建一個集成于 UIView 的類來展示RN界面 我這里叫ReactView
ReactView.m

#import "ReactView.h"
#import <RCTRootView.h>
@implementation ReactView
-(instancetype)initWithFrame:(CGRect)frame{
    self =[super initWithFrame:frame];
    if (self) {
        NSString * strUrl = @"http://localhost:8081/index.ios.bundle?platform=ios&dev=true";
        NSURL * jsCodeLocation = [NSURL URLWithString:strUrl];
        // 這里的moduleName一定要和下面的index.ios.js里面的注冊一樣
        RCTRootView * rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation  moduleName:@"IOSRN"
                                                      initialProperties:nil
                                                          launchOptions:nil];
        
        [self addSubview:rootView];
        
        rootView.frame = self.bounds;
    }
    return self;

}

最后我們把View貼到ViewController上面

ReactView * reactView = [[ReactView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
[self.view addSubview:reactView];

在iOS項目中Info.plist文件下添加

    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>

最后把RN的服務(wù)器打開( 一定等服務(wù)器運行起來 在運行項目)

 # 找到根目錄
    $ react-native start

運行項目 這些就是從原生iOS項目跳轉(zhuǎn)RN 下面再說下從RN跳回原生iOS項目??
————————————————————————————————————————————
之前是寫的比較簡單所以沒有多建頁面 下面因為要跳轉(zhuǎn) 所以頁面比較多如果看不懂的可以看下git上的demo
從RN跳回原生iOS項目:https://github.com/gjjggg/iOSRN.git
1.新建 RCTModules 類,繼承 NSObject 封裝一個方法使用“通知”進(jìn)行消息的傳送從而實現(xiàn)頁面的跳轉(zhuǎn)
RCTModules類
RCTModules.h

#import <Foundation/Foundation.h>
// 導(dǎo)入RCTBridgeModule類,這個是react-native提供
#import "RCTBridgeModule.h"
// 遵守RCTBridgeModul協(xié)議
@interface RCTModules : NSObject<RCTBridgeModule>

@end

RCTModules.m

#import "RCTModules.h"
#import "RCTBridge.h"
@implementation RCTModules
RCT_EXPORT_MODULE(RTModule)
//RN跳轉(zhuǎn)原生界面
RCT_EXPORT_METHOD(RNOpenOneVC:(NSString *)msg){
    
    NSLog(@"RN傳入原生界面的數(shù)據(jù)為:%@",msg);
    //主要這里必須使用主線程發(fā)送,不然有可能失效
    dispatch_async(dispatch_get_main_queue(), ^{
       
    [[NSNotificationCenter defaultCenter]postNotificationName:@"RNOpenOneVC" object:nil];
    });
}
@end

2.接下來在TwoViewController.m中添加通知的方法
TwoViewController.m

#import "TwoViewController.h"
#import "ReactView.h"
//要跳轉(zhuǎn)的原生界面
#import "ThreeViewController.h"
@interface TwoViewController ()

@end

@implementation TwoViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    self.navigationController.navigationBarHidden = YES;
    
   
    
    //self.navigationItem.title = @"我是包含RN的原生頁面喲~";
    ReactView * reactView = [[ReactView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width,  self.view.frame.size.height)];
    [self.view addSubview:reactView];
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doPushNotification:) name:@"RNOpenOneVC" object:nil];
}

- (void)doPushNotification:(NSNotification *)notification{
    NSLog(@"成功收到===>通知");
    ThreeViewController *one = [[ThreeViewController alloc]init];

    
    [self.navigationController pushViewController:one animated:YES];
    
    //注意不能在這里移除通知否則pus進(jìn)去后有pop失效
}

3.創(chuàng)建ThreeViewController繼承于UIViewController
4.最后RN中的界面 我是自己建了一個Two界面代碼如下

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
//需要導(dǎo)入NativeModules組件,這個是官方提供給我們與原生交互的組件,通過它我們才能調(diào)用到原生的方法
    NativeModules
} from 'react-native';
// 看到 RTModule 是不是很熟悉,沒錯這個就是原生中寫的那個類
// 后面一定要一樣哦
var RNModules  = NativeModules.RTModule;
export default class Home extends Component {
    render() {
        return (
            <View style={styles.container}>
              // RNOpenOneVC這個也是寫在原生里面的再RNModules中哦~
                <Text style={styles.instructions} onPress={()=>RNModules.RNOpenOneVC('測試')} >
                我還是RN界面, 點我才能回原生哦
                </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,
    },
});
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,351評論 25 708
  • React Native學(xué)習(xí)<一> 認(rèn)識Recat Native 博客原文:http://www.jianshu....
    AFinalStone閱讀 2,824評論 0 12
  • 想了很久,要先介紹各種組件的實際應(yīng)用好,還是先介紹怎么把React Native集成到原生項目好。因為想起,一旦開...
    朱_源浩閱讀 23,075評論 84 129
  • 今天(2016.11.3晚),在簡書上創(chuàng)建了自己的新文集和新專題——音為有你。不是一時的沖動,而是從接觸簡書第二天...
    春耕秋實閱讀 222評論 0 0
  • 迷迷糊糊地睜開眼,刺鼻的消毒水味彌漫在空氣中。周圍一片安靜,我以為自己進(jìn)了太平間,嚇得后背冒出了冷汗。 低著纏著紗...
    王曉白閱讀 299評論 0 0

友情鏈接更多精彩內(nèi)容