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.開發環境准備
- 基礎環境 首先要安裝React Native在iOS平台上所需的一切依賴軟件(如npm,node等) --- RN開發環境搭建傳送門
- CocoaPods環境 cocoaPods是針對iOS和Mac開發的包管理工具,做過開發的並使用它管理過三方庫的一點都不陌生,同樣RN框架的代碼也通過它來下載並添加到項目中。 ---- cocoaPods安裝使用教程傳送門
3.示例APP
示例程序采用2048小游戲,下面是尚未植入RN時候的頁面

4.依賴包
React Native的植入過程中需要React 和 React Native兩個node依賴包。
package.json
具體的依賴包會記錄在 package.json 文件中,如果項目中沒有的自己創建吧(推薦使用 Sublime Text)
對於一個典型的RN項目來說,一般package.json和index.ios.js等文件會放在項目的根目錄下。而iOS相關的源代碼會放在一個名為 ios/ 的子目錄中,這里同樣放着Xcode項目文件(.xcodeproj)
下面是我的package.json示例
示例中的version字段沒有太大意義(除非你要把你的項目發布到npm倉庫)。scripts中是用於啟動packager服務的命令。dependencies中的react和react-native的版本取決於你的具體需求。一般來說我們推薦使用最新版本。你可以使用npm info react和npm 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的過程在國內非常不順利,請自行配備穩定的翻牆工具,或是嘗試一些鏡像源):
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了中。

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會出現如下頁面,表示集成成功了

至此,就可以做功能的開發了。
