react native 集成到 ios 项目中

出于公司需求,需要再已经运行了5年的项目中添加react native .看到网上基本上就是照抄RN中文网的, 时间也很久了, 把自己集成的过程记录下,尝试总结下 ,希望帮助需要的人吧。

  • rn中文网"集成到现有原生应用"总结的不错 在这里贴出来

1.RN环境

我们的开发电脑安装RN的环境, 这里就不多做介绍了,RN中文网写的很详细。

2. 安装 JavaScript 依赖包

在项目根目录下创建一个名为package.json的空文本文件,填入内容,填入什么内容呢?
其实你可以使用react-native init 项目名命令创建一个纯RN项目,然后去参考其ios目录中的package.json 和 Podfile文件【备注:RN的最新版本0.6+开始使用cocopods管理ios项目,并管理ios和RN的项目依赖】

这里简单贴一下示例:
package.json

{
  "name": "myRactNative",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "start": "react-native start",
    "test": "jest",
    "lint": "eslint ."
  },
  "dependencies": {
    "react": "16.9.0",
    "react-native": "0.61.5"
  },
  "devDependencies": {
    "@babel/core": "^7.8.7",
    "@babel/runtime": "^7.8.7",
    "@react-native-community/eslint-config": "^0.0.7",
    "babel-jest": "^25.1.0",
    "eslint": "^6.8.0",
    "jest": "^25.1.0",
    "metro-react-native-babel-preset": "^0.58.0",
    "react-test-renderer": "16.9.0"
  },
  "jest": {
    "preset": "react-native"
  }
}

然后运行yarn add react-native
这样默认会安装最新版本的 React Native,同时会打印出类似下面的警告信息(你可能需要滚动屏幕才能注意到):
warning "[email protected]" has unmet peer dependency "[email protected]".
这是正常现象,意味着我们还需要安装指定版本的 React:
yarn add [email protected]
注意必须严格匹配警告信息中所列出的版本,高了或者低了都不可以。
如果你使用多个第三方依赖,可能这些第三方各自要求的 react 版本有所冲突,此时应优先满足react-native所需要的react版本。其他第三方能用则用,不能用则只能考虑选择其他库。

3. 安装 Cocopods 依赖包

Podfile

platform :ios, '9.0'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

target 'myRactNative' do
  # Pods for myRactNative
  pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
  pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
  pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
  pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
  pod 'React', :path => '../node_modules/react-native/'
  pod 'React-Core', :path => '../node_modules/react-native/'
  pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
  pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
  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-Core/RCTWebSocket', :path => '../node_modules/react-native/'

  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 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon"
  pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
  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'

  target 'myRactNativeTests' do
    inherit! :search_paths
    # Pods for testing
  end

  use_native_modules!
end

target 'myRactNative-tvOS' do
  # Pods for myRactNative-tvOS

  target 'myRactNative-tvOSTests' do
    inherit! :search_paths
    # Pods for testing
  end

end

这里需要注意两点

【1】Podfile 文件中,node_modules 目录一般位于根目录中 但是如果你的结构不同,那你就要根据实际路径修改下面的:path =>

我贴一下我示例项目中的目录结构


截屏2020-03-1010.51.01.png
【2】Podfile 文件中,platform :ios, '9.0' 这个要注意 一定最低是9.0 否则pod instal的时候会出现类似Folly glog DoubleConversion 安装不上,包错误❌的问题。可以试一下。

剩下的就是 pod install了,如果这个过程不出错,恭喜你!!已经基本完成了项目集成RN的工作~

其实说白了 就两大步, 搞定package.jsonPodfile

剩下的就是在根目录中新建一个index.js的RN入口文件,和在OC中调用进入RN场景的代码了,这里简单贴一下代码:

index.js

/**
 * @format
 */

import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';

AppRegistry.registerComponent(appName, () => App);

native view -> 跳转RN

/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#import "AppDelegate.h"

#import 
#import 
#import 

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"myRactNative"
                                            initialProperties:nil];

  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  return YES;
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

@end

4. 下面我说下 我项目中遇到的坑

【1】Pods/boost-for-react-native/boost/compatibility/cpp_c_headers/cstdlib:11:11: error: no member named 'abort' in the global namespace

解决办法: Xcode: cstdlib no member named “xxx” in the global namespace

最后的最后, 我兴奋的运行了起来, 完美 perfect !成功了耶,于是打包测试, WC,跳转到RN界面 居然 闪退了!!!

嘚吧了那么多,其实还有一小点需要我们注意,这个是原项目集成RN中容易忽略的点,

先解释一下吧,
其实在release 环境下打包 代码中有这样一句

  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];

那么这个main.jsbundle怎么生成呢,我也网上找了rn代码打包成bundle的命令 , 什么使用curl命令生成 main.jsbundle 还有什么react-native bundle --entry-file index.ios.js --bundle-output ./bundle/ios/index.ios.jsbundle --platform ios --assets-dest ./bundle/ios --dev false
我都试一试了,反正在我这边都不行, 打包后一跳转RN界面就会闪退,

其实在RN中文网集成到现有项目中一段未翻译的英文标注

When moving your app to production, the NSURL can point to a pre-bundled file on disk via something like [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];. You can use the react-native-xcode.sh script in node_modules/react-native/scripts/ to generate that pre-bundled file.
就是这个 react-native-xcode.sh script脚本

这个 react-native-xcode.sh script脚本 添加到 你项目中

截屏2020-03-1011.26.59.png

就是这个Bundle React Native code and images 内容如下:

export NODE_BINARY=node
../node_modules/react-native/scripts/react-native-xcode.sh

截屏2020-03-1011.29.34.png

注意路径哦,个别项目可能不同

~ 另外 我的项目 刚集成了 RN 的热更库 微软的 code-push 有时间写也一下集成历程...

到此真正的结束了,你可以愉快的 codeing rn 代码了...

你可能感兴趣的:(react native 集成到 ios 项目中)