將React Native 集成進現有OC項目中(過程記錄) 、jsCodeLocation 生成方式總結


將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

$ cd /Users/galahad/Desktop/ziliao/OC項目集成RN/RNComponent 
$ touch package.json
 
package.josn 中的內容如下,其中name位App的名字,dependencies為react和react-native的版本,在創建這些信息時,建議利用react-native init AwesomeProject新建新項目時會自動創建package.json,直接把文件復制過來,更改name為自己的原生項目名,確保信息為最新的,且不容易出錯。
 


3、安裝React Native依賴包
進入到RNComponent文件夾下運行命令行,npm install。
$ cd /Users/galahad/Desktop/ziliao/OC項目集成RN/yooweiRN/RNComponent 
$ npm install
執行結束后項目中會多出一個node_modules文件夾
 
使用鏡像文件,執行很快
added 1033 packages from 527 contributors in 37.502s
 
4、創建入口文件index.js、參考官方生成的RN項目里面的文件
$ cd /Users/galahad/Desktop/ziliao/OC項目集成RN/yooweiRN/RNComponent
$ touch index.js
$ touch App.js
$ touch app.json


5. Cocoapods集成React Native

終端命令cd 到項目跟目錄

$ cd /Users/galahad/Desktop/ziliao/OC項目集成RN/yooweiRN 
 
創建Podfile文件:
$ touch Podfile
$ open -e podfile
$ cd /Users/galahad/Desktop/ziliao/OC項目集成RN/yooweiRN 
$ pod install
(1)在安裝的過程中遇到好多以前沒有遇到的問題,下面一一記錄下來,以供參考:
[!] CocoaPods could not find compatible versions for pod "React/BatchedBridge":
  In Podfile:
    React/BatchedBridge (from `./RNComponent/node_modules/react-native`)
None of your spec sources contain a spec satisfying the dependency: `React/BatchedBridge (from `./RNComponent/node_modules/react-native`)`.
You have either:
 * out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
 * mistyped the name or version.
 * not added the source repo that hosts the Podspec to your Podfile.
Note: as of CocoaPods 1.0, `pod repo update` does not happen on `pod install` by default.
然后我按照要求進行升級,升級的過程中又遇到了另外一個問題。(先透漏下,最終的原因不是因為沒有升級,后面會講到)
 
$ pod repo update
 遇到了一個問題
  /usr/bin/git -C /Users/galahad/.cocoapods/repos/WYNetWorking fetch origin --progress
  remote: Repository not found.
  fatal: repository 'https://github.com/yoowei/WYNetWorking.git/' not found
[!] CocoaPods was not able to update the `WYNetWorking` repo. If this is an unexpected issue and persists you can inspect it running `pod repo update --verbose`
 
這個是我原來自己建的庫,已經廢棄了,github上面的庫已經刪除,所以此次報這個錯誤。進入這個/Users/galahad/.cocoapods/repos/WYNetWorking目錄下,將其刪掉即可。
 
之后,還是報上面那個錯誤
 
[!] CocoaPods could not find compatible versions for pod "React/BatchedBridge":
 
那么我就認為這個根本就不是什么cocoapods 升不升級的問題,而是依賴存不存在的問題,所以在podfile 里面直接將BatchedBridge 刪掉,然后pod install 能夠成功。但是整個項目卻報一堆錯誤
 
Undefined symbols for architecture x86_64:
  "_OBJC_CLASS_$_RCTDevMenuItem", referenced from:
      objc-class-ref in RCTPerfMonitor.o
  "facebook::react::parseTypeFromHeader(facebook::react::BundleHeader const&)", referenced from:
      +[RCTJavaScriptLoader attemptSynchronousLoadOfBundleAtURL:runtimeBCVersion:sourceLength:error:] in RCTJavaScriptLoader.o
 
  。。。(省略)
 
  "_OBJC_CLASS_$_RCTInspectorDevServerHelper", referenced from:
      objc-class-ref in RCTBridge.o
      objc-class-ref in RCTDevSettings.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
 
轉變思路,應該是引用的三方依賴庫文件不對,這個時候,參考  https://reactnative.cn/docs/integration-with-existing-apps/
 
 
參考之后( 注意可能不同版本不一樣),編輯podfile 文件,如下:

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

然后pod install 又特么出問題了
$ pod install
Analyzing dependencies
Fetching podspec for `DoubleConversion` from `./RNComponent/node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`
Fetching podspec for `Folly` from `./RNComponent/node_modules/react-native/third-party-podspecs/Folly.podspec`
Fetching podspec for `React` from `./RNComponent/node_modules/react-native`
Fetching podspec for `glog` from `./RNComponent/node_modules/react-native/third-party-podspecs/glog.podspec`
Fetching podspec for `yoga` from `./RNComponent/node_modules/react-native/ReactCommon/yoga`
Downloading dependencies
Installing DoubleConversion (1.1.6)
Installing Folly (2016.10.31.00)
Using React (0.57.1)
Installing boost-for-react-native (1.63.0)
Installing glog (0.3.5)
[!] /bin/bash -c 
set -e
#!/bin/bash
set -e
 
PLATFORM_NAME="${PLATFORM_NAME:-iphoneos}"
CURRENT_ARCH="${CURRENT_ARCH}"
 
......(省略)
 
xcrun: error: SDK "iphoneos" cannot be located
xcrun: error: SDK "iphoneos" cannot be located
xcrun: error: SDK "iphoneos" cannot be located
xcrun: error: unable to lookup item 'Path' in SDK 'iphoneos'
/Users/galahad/Library/Caches/CocoaPods/Pods/External/glog/2263bd123499e5b93b5efe24871be317-e8acf/missing: Unknown `--is-lightweight' option
Try `/Users/galahad/Library/Caches/CocoaPods/Pods/External/glog/2263bd123499e5b93b5efe24871be317-e8acf/missing --help' for more information
configure: WARNING: 'missing' script is too old or missing
configure: error: in `/Users/galahad/Library/Caches/CocoaPods/Pods/External/glog/2263bd123499e5b93b5efe24871be317-e8acf':
configure: error: C compiler cannot create executables
See `config.log' for more details
 
然后執行下面命令:
$ sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer/
輸入mac密碼
Password:
重新安裝
$ pod install
安裝沒有問題,工程運行OK .
 

三、項目處理

項目目錄:整個工程中新建一個文件夾 RNComponent ,用來裝RN相關資料,顯得整潔,便於管理。
 
工程目錄結構:
 
注意工程目錄結構中並沒有將 RNComponent 拖進去,因為cocopods 已經引用過了相關的東西。
 
1、配置App Transport Security

在iOS 9以上的系統中,除非明確指明,否則應用無法通過http協議連接到localhost主機。 建議在Info.plist進行如下設置,否則會報Could not connect to development server錯誤。

 

2、添加RCTRootView
這里只是在ViewController中進行了測試,具體放在什么地方,怎么放置大家根據項目需求而定。
 

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

說明:

上面的兩個例子,JS代碼包URL的獲取是通過RCTBundleProvider這個類實現的。JS代碼包的URL有兩種可能結果,一種是Packager Server URL,一種是本地JS代碼包的文件路徑。通過 jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];去獲取JS代碼包URL時,會首先檢查是否有正在運行的Packager Server,如果有則返回相應Packager Server中JS代碼包的絕對路徑;如果沒有正在運行的Packager Server,則會返回一個本地JS代碼包的文件路徑,不傳遞 fallbackResource參數時,默認返回 本地 main.jsbundle的文件路徑。



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM