【2017.5.2更新】使用Cocoapods集成的確方便,但在引用一些不支持Cocoapods的第三方RN庫時(shí)會有依賴問題畸冲。而且貌似Cocoapods上的更新也稍顯滯后,所以還是推薦使用npm集成款熬,這里推薦另一篇文章iOS現(xiàn)有項(xiàng)目集成React Native。
最近在學(xué)習(xí)React Native, 相當(dāng)一部分學(xué)習(xí)文檔在React Native中文網(wǎng)上都有相應(yīng)的中文翻譯吱瘩,而且比官網(wǎng)更為詳盡起來在某些描述下更為詳盡杖爽。但因?yàn)橹形木W(wǎng)的翻譯工作尚未完全結(jié)束帚豪,部分文檔還需從閱讀官網(wǎng)的英文原文〕锨罚現(xiàn)對針對嵌入到現(xiàn)有iOS項(xiàng)目部分Integration With Existing Apps進(jìn)行一下總結(jié)嘁锯,方便日后查閱。
要嵌入React Native到iOS項(xiàng)目中基本包含以下幾步:
- 1.通過npm在工程中下載React及React Native的node模組
- 2.通過CocoaPods下載組件framework
- 3.代碼實(shí)現(xiàn)
- 4.運(yùn)行測試
1.通過npm在工程中下載React及React Native的node模組
- 在項(xiàng)目根目錄下創(chuàng)建包依賴文件(package dependencies)
package.json
聂薪,內(nèi)容如下
{
"name": "NumberTileGame",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start"
},
"dependencies": {
"react": "15.3.2",
"react-native": "0.37.0"
}
}
react和react-native盡量使用最新的版本,舊的版本項(xiàng)目編譯時(shí)可能報(bào)錯(cuò)(官網(wǎng)教程中用到的"react": "15.0.2", "react-native": "0.26.1"我就不能編譯通過)蝗羊。查詢當(dāng)前版本可以使用以下命令:
npm info react
npm info react-native
- 包安裝
在package.json
文件所在目錄執(zhí)行命令安裝組件,模組最后會裝node_modules/
目錄下
npm install
2.通過CocoaPods下載組件framework
- 創(chuàng)建
Podfile
文件藏澳,在.xcodeproj
文件所在目錄下執(zhí)行
pod init
在Podfile
文件下指定具體安裝哪些React Native的依賴庫。所指定的每一個(gè)庫就都稱為一個(gè)subspect
耀找,具體支持的subspect
可以在node_modules/react-native/React.podspec
中查看翔悠。以下是一個(gè)事例:
target 'YourProject' do
# Uncomment this line if you're using Swift or would like to use dynamic frameworks
# use_frameworks!
pod 'React', :path => 'node_modules/react-native', :subspecs => [
'Core',
'RCTText',
'RCTNetwork',
'RCTWebSocket', # needed for debugging
# Add any other subspecs you want to use in your project
]
# Pods for YourProject
end
- 開始安裝
pod install
3.代碼實(shí)現(xiàn)
React Native 部分
創(chuàng)建React Native 的頁面入口文件index.ios.js
,以官方提供的2048分?jǐn)?shù)頁面為例子野芒。
'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,
},
});
// Module name
AppRegistry.registerComponent('RNHighScores', () => RNHighScores);
原生部分
在UIViewController
中引入RCTRootView
#import "RCTRootView.h"
創(chuàng)建頁面
NSURL *jsUrl = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios"];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL : jsUrl
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];
index.ios.js
是官方的默認(rèn)文件名稱蓄愁,但經(jīng)過試驗(yàn),用其他名字也是可以的狞悲,只要加載的時(shí)候根據(jù)具體的名稱加載就可以了撮抓,感覺可以通過這個(gè)特點(diǎn)創(chuàng)建多個(gè)模塊入口供原生使用。
4.運(yùn)行測試
App Transport Security
一個(gè)小坑摇锋,在iOS9之后默認(rèn)只支持Https協(xié)議的網(wǎng)絡(luò)訪問丹拯,閱讀文檔時(shí)也看到了,但來回配幾次就忘了荸恕,導(dǎo)致后續(xù)頁面總是加載失敗乖酬。Info.plist
需要配置如下:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
運(yùn)行Packager
在工程根目錄(node_modules所在目錄)運(yùn)行如下語句
npm start
運(yùn)行App
在Xcode中運(yùn)行工程或在根目錄執(zhí)行react-native run-ios
命令。
雖然在官方文檔中提到可以用
react-native run-ios
命令運(yùn)行融求,但在試驗(yàn)過程中一直未能成功咬像,報(bào)ENOENT: no such file or directory, uv_chdir
錯(cuò)誤,原因未明。
大功告成县昂,以上肮柜。