將RN集成到現有OC項目應該是最常見的,特別是已經有OC項目的,不太可能會去專門搞個純RN的項目。又因為RN不同版本,引用的依賴可能不盡相同,所以特別說明下,本文參考的文檔是React Native (0.57)相關文檔。
一、准備工作
本文演示項目基於如下版本:
"react": "16.5.0",
"react-native": "0.57.1"
1、RN搭建開發環境
如果你已經創建過RN項目,並且運行成功了,那么你的環境配置應該是沒有問題的,但是如果你是第一次進行學習,那么就要搭建開發環境了,具體的可以參考: React Native (0.57)開發環境搭建(過程記錄)
2、安裝CocoaPods
沒有安裝過CocoaPods的,可以參考:CocoaPods :為iOS程序提供依賴管理的工具(yoowei)
二、集成ReactNative
1、新建一個OC項目
任意地方,創建一個文件夾“OC項目集成RN”,創建一個yooweiRN的OC項目,用為已有OC項目。如下:

2、終端命令 cd 到該項目跟目錄。創建文件夾RNComponent (文件夾名字可以自定義,主要用來存放RN相關的文件)和配置文件package.json
3、安裝React Native依賴包



5. Cocoapods集成React Native
終端命令cd 到項目跟目錄
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'
use_frameworks!
target 'yooweiRN' do
# 'node_modules'目錄一般位於根目錄中 。但是如果你的結構不同,那你就要根據實際路徑修改下面的`:path`
pod 'React', :path => './RNComponent/node_modules/react-native', :subspecs => [
'Core',
'ART',
'RCTActionSheet',
'RCTGeolocation',
'RCTImage',
'RCTNetwork',
'RCTPushNotification',
'RCTSettings',
'RCTText',
'RCTVibration',
'RCTWebSocket',
'RCTLinkingIOS',
'RCTAnimation',
'CxxBridge',
'DevSupport',
]
pod 'yoga', :path => './RNComponent/node_modules/react-native/ReactCommon/yoga'
pod 'DoubleConversion', :podspec => './RNComponent/node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
pod 'glog', :podspec => './RNComponent/node_modules/react-native/third-party-podspecs/glog.podspec'
pod 'Folly', :podspec => './RNComponent/node_modules/react-native/third-party-podspecs/Folly.podspec'
target 'yooweiRNTests' do
inherit! :search_paths
# Pods for testing
end
target 'yooweiRNUITests' do
inherit! :search_paths
# Pods for testing
end
end
三、項目處理
在iOS 9以上的系統中,除非明確指明,否則應用無法通過http協議連接到localhost主機。 建議在Info.plist進行如下設置,否則會報Could not connect to development server錯誤。

3、開啟RN本地服務(cd 到RNComponent目錄)
$ cd /Users/galahad/Desktop/ziliao/OC項目集成RN演練/yooweiRN/RNComponent
$ react-native start

不出意外的是下面這個場景

原因:打印日志看看

由於RN不同版本,入口文件名不同,根據實際入口文件名,修改之后。

模擬器展示如下:

4G真機上面運行失敗 :(正常現象)
Failed to load bundle(http://localhost:8081/index.bundle?platform=ios&dev=true) with error:(Could not connect to development server.
wifi真機上面運行失敗:
Ensure the following:
- Node server is running and available on the same network - run 'npm start' from react-native root
- Node server URL is correctly set in AppDelegate
- WiFi is enabled and connected to the same network as the Node Server
URL: http://localhost:8081/index.bundle?platform=ios&dev=true Could not connect to the server.)
打開偏好設置-網絡-查看當前ip地址,將項目中的localhost改為當前ip(注意,手機的wifi應當和電腦連接的是同一個網絡才可以)


至此,將RN集成進OC項目中,並簡單的運行起來,告一段落。下面待續......
jsCodeLocation生成方式總結:
NSURL *jsCodeLocation;
/**
* OPTION 1: development
* Load from development server. Start the server from the repository root:
* $ npm start
* To run on device, change `localhost` to the IP address of your computer, and make sure your computer and iOS device are on the same Wi-Fi network.
*/
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.bundle?platform=ios&dev=true"];
/**
* OPTION 2:Release
* Load from pre-bundled file on disk. The static bundle is automatically generated by the "Bundle React Native code and images" build step when running the project on an actual device or running the project on the simulator in the "Release" build configuration.
*/
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
另外實際項目中,還有如下寫法:
#ifdef DEBUG
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
#else
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"bundle/index.ios" withExtension:@"jsbundle"];
#endif
如果項目中使用了CodePush的話,還有如下寫法
#ifdef DEBUG
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
jsCodeLocation = [CodePush bundleURL];
#endif
說明:
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];去獲取JS代碼包URL時,會首先檢查是否有正在運行的Packager Server,如果有則返回相應Packager Server中JS代碼包的絕對路徑;如果沒有正在運行的Packager Server,則會返回一個本地JS代碼包的文件路徑,不傳遞
fallbackResource參數時,默認返回 本地
main.jsbundle的文件路徑。
