在現有的iOS工程中集成react native, 或者說將react native引入到iOS 項目,是RN和iOS混合開發的必經之路node
參考官網教程:https://reactnative.cn/docs/integration-with-existing-apps/react
可是會有一些步驟報錯,這裏記錄一下。首先個人項目結構是這樣:ios
RNTEST 是最外面的文件夾的名字,也是iOS項目的名字。ios/ 下是iOS項目文件。git
npm安裝RN依賴都沒問題,按照官網步驟來github
最主要的是npm
cd iosjson
pod installreact-native
會報錯。。。app
錯誤提示是找不到XXX索引庫,在Podfile文件中將這些對應的註釋掉:ide
Podfile文件參考:https://github.com/facebook/react-native/blob/v0.60.0/template/ios/Podfile
platform :ios, '9.0' require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' target 'RNTEST' do # Pods for HelloWorld pod 'React', :path => '../node_modules/react-native/' pod 'React-Core', :path => '../node_modules/react-native' #pod 'React-DevSupport', :path => '../node_modules/react-native/React' #pod 'React-fishhook', :path => '../node_modules/react-native/Libraries/fishhook' pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS' pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation' pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob' pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image' pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS' pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network' pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings' pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text' pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration' #pod 'React-RCTWebSocket', :path => '../node_modules/react-native/Libraries/WebSocket' pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact' pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi' pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor' pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector' pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga' pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' use_native_modules! end
結果:
以後就是在iOS工程中寫相關代碼, 能夠運行起來,可是在Native調RN時
而後發現又報錯了,改了package.json中的版本以下:
就能夠了。
iOS項目代碼參考的是慕課網上的教程。
要想在iOS中加載一個JSX頁面,有兩種方式:
一:在控制器導入頭文件
//#import <React/RCTBundleURLProvider.h> //#import <React/RCTRootView.h> //#import <React/RCTEventEmitter.h>
而後加載JSX中註冊的模塊
// NSURL *jsCodeLocation; // // jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; // // RCTRootView *rootView = // [[RCTRootView alloc] initWithBundleURL: jsCodeLocation // moduleName: @"App" // initialProperties:nil // launchOptions: nil]; // self.view = rootView;
上面這個moduleName (任意取,可是要與OC中一致才能加載對應頁面)就是在index.js中的這個:
import {AppRegistry} from 'react-native' import App from './App'; import App2 from './App2'; AppRegistry.registerComponent('App1',()=>App); AppRegistry.registerComponent('App2',()=>App2); AppRegistry.registerComponent('App3',()=>App2);
二:借鑑AppDelegate中加載方式,首先導入頭文件,遵循代理,實現代理方法,加載index.js中的模塊
// // RNPageController.m // RNTEST // // Created by LiuWei on 2019/10/18. // Copyright © 2019 udc. All rights reserved. // #import "RNPageController.h" //#import <React/RCTBundleURLProvider.h> //#import <React/RCTRootView.h> //#import <React/RCTEventEmitter.h> #import <React/RCTBridge.h> #import <React/RCTBundleURLProvider.h> #import <React/RCTRootView.h> @interface RNPageController ()<RCTBridgeDelegate> @end @implementation RNPageController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. // [self initRCTRootView]; RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:nil]; RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"App1" initialProperties:nil]; self.view=rootView; } //-(void)initRCTRootView{ // NSURL *jsCodeLocation; // // jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; // // RCTRootView *rootView = // [[RCTRootView alloc] initWithBundleURL: jsCodeLocation // moduleName: @"App" // initialProperties:nil // launchOptions: nil]; // self.view = rootView; //} - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { #if DEBUG return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; #else return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; #endif } @end
以上這種開發方式最終打包 ipa時,
先在ios/ 下建立一個 release_ios/
而後執行命令生成必要的jsbundle文件和圖片資源文件
react-native bundle --entry-file index.js --platform ios --dev false --bundle-output release_ios/main.jsbundle --assets-dest release_ios/
--platform ios
:表明打包導出的平臺爲iOS;--dev false
:表明關閉JS的開發者模式;-entry-file index.js
:表明js的入口文件爲index.js
;--bundle-output
:後面跟的是打包後將JS bundle包導出到的位置;--assets-dest
:後面跟的是打包後的一些資源文件導出到的位置;好了以後將生成必要的jsbundle文件和圖片資源文件拖進iOS項目
接下來就能夠打包了
特別注意:若是項目用到了CodePush熱更新:加載js文件的方式變成這樣
... NSURL *jsCodeLocation; #ifdef DEBUG jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; #else jsCodeLocation = [CodePush bundleURL]; #endif ...
最後Demo地址:https://github.com/nwgdegitHub/OCCallRNDemo.git