react native集成到原有的項(xiàng)目中(iOS)

接觸RN也有一段時(shí)間了,基本上來(lái)說(shuō)算是入門了置逻,到目前RN的應(yīng)用還沒有達(dá)到期望的廣泛度,大部分還是以原生+RN的方式進(jìn)行混合開發(fā),今天抽空寫一下關(guān)于RN嵌入到iOS原生項(xiàng)目中的知識(shí)點(diǎn)鞍恢。

前期準(zhǔn)備

現(xiàn)在大部分嵌入方式都是采用cocoapods的方式引入RN依賴庫(kù)到原生項(xiàng)目中,當(dāng)然你也可以選擇手動(dòng)方式每窖,不過(guò)很麻煩帮掉,本文采用的cocoapods來(lái)管理依賴。
RN所需要的環(huán)境也要裝好窒典,中文網(wǎng)有蟆炊,具體我就不說(shuō)了

集成

用Xcode創(chuàng)建一個(gè)項(xiàng)目,然后在項(xiàng)目中創(chuàng)建一個(gè)目錄瀑志,把RN相關(guān)的都放在里面涩搓,如下圖,我創(chuàng)建了一個(gè)js目錄(這個(gè)目錄你也可以放到iOS項(xiàng)目的根目錄劈猪,任意)昧甘。

示例.png

然后cd到剛剛創(chuàng)建的js目錄中,執(zhí)行npm init战得,創(chuàng)建node環(huán)境充边,這時(shí)js目錄中會(huì)多出一個(gè)package.json文件,這個(gè)文件和iOS中的Podfile類似常侦,是用來(lái)記錄著RN工程中要安裝的依賴浇冰,目前你只需要關(guān)注dependencies這一項(xiàng)(把下面的內(nèi)容覆蓋到你生成的package.json文件中)贬媒,該項(xiàng)中記錄著RN項(xiàng)目要安裝的依賴庫(kù)。

{
  "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包管理器來(lái)安裝RN的依賴庫(kù)肘习,還是在js目錄執(zhí)行npm install,安裝完畢之后际乘,js目錄會(huì)多出一個(gè)名為node_modules文件夾,RN所必須依賴的庫(kù)都在這里面井厌,然后我們創(chuàng)建一個(gè)index.ios.js作為RN項(xiàng)目的入口文件(名字可以任意起)蚓庭,然后我們就可以在入口文件中愉快的寫RN代碼了。

上面的步驟順利執(zhí)行完之后仅仆,RN項(xiàng)目已經(jīng)完成了器赞,現(xiàn)在我們要把RN集成到iOS原生項(xiàng)目中。

在項(xiàng)目根目錄創(chuàng)建一個(gè)Podfile文件墓拜,如下所示港柜,在項(xiàng)目的根目錄執(zhí)行pod install 來(lái)安裝Podfile中指定的依賴庫(kù)。

# 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庫(kù)之后我們就可以著手集成RN了咳榜。

RN為我們?cè)趇OS平臺(tái)上提供了一個(gè)RCTRootView夏醉,RCTRootView是繼承自iOS中UIView類,所以你可以像使用UIView一樣使用RCTRootView涌韩,RN與iOS的交互都要在RCTRootView中進(jìn)行畔柔,本篇文章先不講交互的事,只講集成臣樱,先把代碼貼上靶擦,如下所示:

#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界面的參數(shù)"
                                  }
                              ]
                      };
    
    
    UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake((self.view.bounds.size.width - 300)/2, 200, 300, 40)];
    [btn setTitle:@"點(diǎn)我進(jìn)入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
    //開發(fā)的時(shí)候用雇毫,需要打開本地服務(wù)器
    jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios"];
#else
    //發(fā)布APP的時(shí)候用
    jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"index.ios" withExtension:@"jsbundle"];
#endif
    
    RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL : jsCodeLocation
                                                 moduleName        : @"RNHighScores"
                                                 initialProperties : self.props  //將native數(shù)據(jù)傳送到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];
}

創(chuàng)建RCTRootView玄捕,將RCTRootView添加到VC中的view上就OK了
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"index.ios" withExtension:@"jsbundle"];
這一行你先忽略,后面會(huì)說(shuō)棚放。
然后cd到j(luò)s目錄枚粘,執(zhí)行react-native start或者執(zhí)行npm start,來(lái)啟動(dòng)本地node服務(wù)器飘蚯,如果沒有錯(cuò)誤的話我們就只需最后一步了馍迄,用Xcode打開項(xiàng)目,運(yùn)行項(xiàng)目局骤,大功告成柬姚。

打RN離線包

此時(shí)我們的項(xiàng)目是依賴于剛剛啟動(dòng)的本地服務(wù)器的,要是上線怎么辦庄涡,所以我們需要打個(gè)RN離線包,這樣就可以擺脫本地服務(wù)器了搬设。
進(jìn)入js目錄穴店,創(chuàng)建一個(gè)bundle目錄撕捍,這里面存放打包后的RN資源,包括RN代碼和圖片等靜態(tài)資源泣洞,在js目錄里執(zhí)行下面的打包命令忧风,

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

如果成功的話,在bundle目錄下會(huì)生成存放RN靜態(tài)資源的assert目錄和RN的index.ios.jsbundle代碼文件球凰,將這倆家伙拖進(jìn)Xcode中

拖.png

注意:要以引用的方式拖進(jìn)Xcode中狮腿。

在文章的集成部分我粘貼了一大段代碼,源代碼中有兩句代碼用來(lái)生成RN資源的URL呕诉,第一句是依賴本地服務(wù)器的缘厢,一般調(diào)試RN代碼時(shí)用,第二句是引入打包后的RN資源的URL甩挫,發(fā)布APP的時(shí)候用的贴硫,我用宏來(lái)進(jìn)行控制。

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

注意:假如我們把第一種獲取URL的方式注釋掉伊者,宏也注釋掉英遭,如果iOS項(xiàng)目是DEBUG模式,而我們加載的明明是RN的離線包亦渗,你會(huì)發(fā)現(xiàn)從原生頁(yè)面跳轉(zhuǎn)到RN頁(yè)面的時(shí)候挖诸,頂部的statusBar會(huì)有加載資源的進(jìn)度顯示,不要糾結(jié)法精,運(yùn)行項(xiàng)目的時(shí)候改成release模式就好了多律,來(lái)張效果圖。

友情提示亿虽,在RN中想引入iOS中Assets.xcassets里面的圖片的話可以直接寫圖片的文件名菱涤,如下面這樣。

<Image source={{uri:'happiness.jpg'}} style={styles.happy}/>
ReactNativeDemo.gif
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末洛勉,一起剝皮案震驚了整個(gè)濱河市粘秆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌收毫,老刑警劉巖攻走,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異此再,居然都是意外死亡昔搂,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門输拇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)摘符,“玉大人,你說(shuō)我怎么就攤上這事」淇悖” “怎么了瘩绒?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)带族。 經(jīng)常有香客問(wèn)我锁荔,道長(zhǎng),這世上最難降的妖魔是什么蝙砌? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任阳堕,我火速辦了婚禮,結(jié)果婚禮上择克,老公的妹妹穿的比我還像新娘恬总。我一直安慰自己,他們只是感情好祠饺,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布越驻。 她就那樣靜靜地躺著,像睡著了一般道偷。 火紅的嫁衣襯著肌膚如雪缀旁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天勺鸦,我揣著相機(jī)與錄音并巍,去河邊找鬼。 笑死换途,一個(gè)胖子當(dāng)著我的面吹牛懊渡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播军拟,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼剃执,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了懈息?” 一聲冷哼從身側(cè)響起肾档,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辫继,沒想到半個(gè)月后怒见,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡姑宽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年遣耍,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片炮车。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡舵变,死狀恐怖酣溃,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情棋傍,我是刑警寧澤救拉,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站瘫拣,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏告喊。R本人自食惡果不足惜麸拄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望黔姜。 院中可真熱鬧拢切,春花似錦、人聲如沸秆吵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)纳寂。三九已至主穗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間毙芜,已是汗流浹背忽媒。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留腋粥,地道東北人晦雨。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像隘冲,于是被迫代替她去往敵國(guó)和親闹瞧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容