iOS 已有项目利用Pod集成RN

2023-05-16

一、背景

对于已经存在的iOS项目,以模块化引入,OC与RN混编怎么做呢?

我们可以利用cocopods来集成,直接使用pod install就可以让其他同事也快速集成。

由于RN用npx react-native init NewProject 命令创建的新项目,外层是RN的代码,里面iOS文件夹下才是我们的工程代码,这样显得很杂乱,所以我的想法是在同级目录下创建两个文件夹iOSCode和RNCode,一个放原生的代码,另外一个放RN代码,这样会比较清晰。

目录结构

二、操作

1、环境

"react": "16.13.1",
"react-native": "0.63.4",

2、ruby脚本

pod工具就是通过ruby语言编写的,所以我们可以插入ruby脚本来做一些自动化的操作。 在iOS工程目录下创建ruby脚本文件 Podfile_ReactNative.rb

# 定义一个函数,在 Podfile文件中调用此函数即可
def installReactNativeSdk()

    # 设置 react_native_pods.rb 文件路径
    node_mudle_pod_file = "../RNCode/node_modules/react-native/scripts/react_native_pods.rb"

    # 判断该文件是否存在,如果已经存在,表示RN环境已经配置,如果没有存在表示RN环境还未集成到项目
    if File.exist?(node_mudle_pod_file)
        Pod::UI.puts "\nReactNative 环境已存在!\n\n"
        # 修改路径
        # changePath(node_mudle_pod_file)
    else
        Pod::UI.puts "ReactNative 环境不存在,准备下载···"
        # 判断是否安装 node环境
        if system "node -v > /dev/null"
            # 切换目录到../RNCode/
            if Dir.chdir("../RNCode/")
                # 使用 yarn 或 npm 下载依赖
                if system "yarn install || npm install"
                    Pod::UI.puts "ReactNative 环境安装成功!\n\n"
                    # 修改路径
                    changePath(node_mudle_pod_file)
                else
                    Pod::UI.puts "ReactNative 环境安装失败!请安装yarn,在命令行执行:npm install -g yarn"
                    Kernel.exit(false)
                end
            else
                Pod::UI.puts "不存在RNCode文件夹"
                Kernel.exit(false)
            end
        else
            #如果没有安装,提示自行安装node环境
            Pod::UI.puts "环境下载失败!请先安装node环境,详细见:https://reactnative.cn/docs/environment-setup"
            Kernel.exit(false)
        end
    end
end

# 这个函数将 react_native_pods.rb 文件中 ../node_modules 目录改为当前目录 ./RNCode/node_modules
def changePath(node_mudle_pod_file) 
    configString = ""
    File.open(node_mudle_pod_file, "r+") {|f|
        configString = f.read.gsub(/..\/node_modules/,"../RNCode/node_modules")
    }
    File.open(node_mudle_pod_file,"w"){|f|
        f.write configString
    }
end

3、Podfile文件

# Uncomment the next line to define a global platform for your project

# 设置下载源
source 'https://github.com/CocoaPods/Specs.git'
# 导入我们自定义的脚本
require_relative './Podfile_ReactNative'
# 执行我们编写的RN环境检测代码
installReactNativeSdk()
# 设置RN配置 依赖,这里需要注意,不要使用 ../node_modules/,而是../RNCode/node_modules/
require_relative '../RNCode/node_modules/react-native/scripts/react_native_pods'

platform :ios, '10.0'

target 'iOSCode' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for iOSCode
  
  pod 'Masonry'

  # 设置RN Path 依赖
  use_react_native!(:path => "../RNCode/node_modules/react-native")

end

4、package.json

node所有的依赖配置为 package.json文件控制,依赖全部下载在 node_modules目录下,所以我们在RNCode目录下创建package.json文件

{
  "name": "iOSCode",
  "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.13.1",
    "react-native": "0.63.4",
  },
  "devDependencies": {
    "@babel/core": "^7.14.8",
    "@babel/runtime": "^7.14.8",
    "@react-native-community/eslint-config": "^3.0.0",
    "babel-jest": "^27.0.6",
    "eslint": "^7.31.0",
    "jest": "^27.0.6",
    "metro-react-native-babel-preset": "^0.66.2",
    "react-test-renderer": "16.13.1"
  },
  "jest": {
    "preset": "react-native"
  }
}

5、最后我们执行pod install即可

➜  iOSRNTest git:(main) ✗ pod install
ReactNative 环境不存在,准备下载···
yarn install v1.22.10
warning ../../../package.json: No license field
[1/4] 🔍  Resolving packages...

三、文件过滤

这里需要注意的是,node_modules目录为RN依赖的资源,没必要提交到git工程,可以在.gitignore文件中过滤掉。
目前我们项目通过这中方式快速集成RN,RN的模块直接在对应的位置通过 RCTRootView展示,其他开发者不太需要关心RN的配置,只要会执行 pod install即可!

四、iOS代码部分

如果想在iOS原生页面跳转RN页面怎么做呢?
我们需要封装几个基类,防止每次访问的时候都会重新加载,出现页面的空白

KGRNManager.h

//
//  KGRNManager.h
//  iOSCode
//
//  Created by jm on 2021/7/28.
//

#import <Foundation/Foundation.h>
#import <React/RCTBridge.h>

NS_ASSUME_NONNULL_BEGIN

@interface KGRNManager : NSObject

+ (instancetype)shareInstance;

// 全局唯一的bridge
@property (nonatomic, readonly, strong) RCTBridge *bridge;

@end

NS_ASSUME_NONNULL_END

KGRNManager.m

//
//  KGRNManager.m
//  iOSCode
//
//  Created by jm on 2021/7/28.
//

#import "KGRNManager.h"
#import <React/RCTBundleURLProvider.h>

#import "RCTPushy.h"

@interface KGRNManager ()<RCTBridgeDelegate>

@end

@implementation KGRNManager

static KGRNManager *_instance = nil;
+ (instancetype)shareInstance{
    if (_instance == nil) {
        _instance = [[self alloc] init];
    }
    return _instance;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone{
    if (_instance == nil) {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instance = [super allocWithZone:zone];
        });
    }
    return _instance;
}

-(instancetype)init{
    if (self = [super init]) {
        _bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:nil];
    }
    return self;
}

#pragma mark - RCTBridgeDelegate
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge {
# if DEBUG
    //模拟器
   // return [NSURL URLWithString:@"http://localhost:8081/index.bundle?platform=ios"];
//    return [NSURL URLWithString:@"http://192.168.2.47:8081/index.bundle?platform=ios"];

  //真机,真机和电脑处于同一ip地址
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"main" fallbackResource:nil];
# else
    return [[NSBundle mainBundle] URLForResource:@"index" withExtension:@"jsbundle"];
#endif
}

@end

KGRNBaseVC.h

//
//  KGRNBaseVC.h
//  iOSCode
//
//  Created by jm on 2021/7/28.
//

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface KGRNBaseVC : UIViewController

/**
 传递到React Native的参数
 */
@property (nonatomic, strong) NSDictionary * initialProperty;

/**
 React Native界面名称
 */
@property (nonatomic, copy) NSString * pageName;

+ (instancetype)RNPageWithName:(NSString*)pageName initialProperty:(NSDictionary*)initialProperty;

- (instancetype)initWithPageName:(NSString*)pageName initialProperty:(NSDictionary*)initialProperty;

@end

NS_ASSUME_NONNULL_END

KGRNBaseVC.m

//
//  KGRNBaseVC.m
//  iOSCode
//
//  Created by jm on 2021/7/28.
//

#import "KGRNBaseVC.h"
#import <React/RCTRootView.h>
#import "KGRNManager.h"

@interface KGRNBaseVC ()

@end

@implementation KGRNBaseVC

+ (instancetype)RNPageWithName:(NSString*)pageName initialProperty:(NSDictionary*)initialProperty {
    KGRNBaseVC *vc = [[KGRNBaseVC alloc] initWithPageName:pageName initialProperty:initialProperty];
    return vc;
}

- (instancetype)initWithPageName:(NSString*)pageName initialProperty:(NSDictionary*)initialProperty {
    if (self = [super init]) {
        self.pageName = pageName;
        self.initialProperty = initialProperty;
    }
    return self;
}

//- (void)viewWillAppear:(BOOL)animated{
//    [super viewWillAppear:animated];
//    [self.navigationController setNavigationBarHidden:YES];
//}
//
//- (void)viewWillDisappear:(BOOL)animated{
//    [super viewWillDisappear:animated];
//    [self.navigationController setNavigationBarHidden:NO];
//}

-(void)viewDidLoad {
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(navagateBack) name:@"KGModuleNavigateBack" object:nil];
    
    RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:[KGRNManager shareInstance].bridge
                                                     moduleName:self.pageName
                                              initialProperties:self.initialProperty];
    self.view = rootView;
}

- (void)navagateBack {
    [self.navigationController popViewControllerAnimated:YES];
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}


@end

当我们需要在原生页面跳转到RN页面的时候,可以创建一个KGRNBaseVC控制器push进入

//  ViewController.m
//  iOSCode
//
//  Created by jm on 2021/7/27.
//

#import "ViewController.h"
#import <React/RCTRootView.h>
#import "KGRNBaseVC.h"
#import <Masonry/Masonry.h>

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self prepareUI];
}

- (void)prepareUI {
    self.title = @"React-Native";
    self.view.backgroundColor = [UIColor whiteColor];
    
    UIButton *btn1 = [[UIButton alloc] init];
    [btn1 addTarget:self action:@selector(btn1Action) forControlEvents:UIControlEventTouchUpInside];
    [btn1 setTitle:@"视图1" forState:UIControlStateNormal];
    [btn1 setBackgroundColor:[UIColor grayColor]];
    [self.view addSubview:btn1];
    
    CGFloat gap = KGScreenZoom(10);
    CGFloat width = (KGScreenW - gap)/ 4.0;
    [btn1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.view.mas_top).offset(KGNaviBarH + gap);
        make.left.equalTo(self.view.mas_left).offset(gap);
        make.width.mas_equalTo(width);
    }];
}

- (void)btn1Action {
    NSDictionary *dic = @{
        @"scores" : @[
          @{
            @"name" : @"Alex",
            @"value": @"AAAAAA"
           },
          @{
            @"name" : @"Joel",
            @"value": @"10"
          }
        ]
    };
    KGRNBaseVC *aVC = [[KGRNBaseVC alloc] initWithPageName:@"AView" initialProperty:dic];
    [self.navigationController pushViewController:aVC animated:YES];
}

@end
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS 已有项目利用Pod集成RN 的相关文章

随机推荐

  • 腾讯云短信服务(详细教程-Django框架、API接口)实现

    今天和大家分享如何实现短信服务 xff0c 以腾讯云服务为例 目录 一 准备工作 二 短信服务接口开发 2 1 服务配置 2 2接口开发 三 测试短信服务 四 结束语 一 准备工作 腾讯云短信服务会发放免费的个人认证短信和赠送短信总共200
  • Pytest测试框架基础篇

    今天和大家分享一下pytest测试框架的基础篇 xff0c 内容包括 xff1a 了解pytest测试框架的特点 掌握pytest基本使用 掌握pytest常用的场景 掌握pytest运行参数和配置方法 目录 一 测试框架的作用和类型 1
  • Pytest测试框架进阶篇

    今天和大家分享pytest测试框架进阶篇 xff0c 也可以称之为pytest测试框架核心 xff0c 主要核心有 xff1a 掌握pytest fixture 掌握pytest mark 目录 一 掌握pytest fixture 1 1
  • PowerDesigner--快速创建表模型生成SQL语句

    今天和大家分享一个我常用的设计表模型的工具PowserDesigner 选择物理模型 创建表 字段 索引等 梳理表之间的关系 一键生成SQL语句 目录 一 准备工作 二 选择物理模型 三 创建表 字段等 3 1 创建表 3 2 创建字段 3
  • python读取txt文件内容并进行分析

    今天和大家分享一下python如何读取txt文件内容并进行数据分析的 需求 某txt文件中存在很多数据 这些数据的某一个属性主要分为A B C D四类 xff0c 要求把数据分成四类求某一数值属性的平均值 xff0c 并统计生成超过平均值两
  • python脚本控制服务器---paramiko的使用

    今天和大家分享一个第三方库paramiko xff0c 主要应用场景是在实现自动化操作服务器时使用 xff0c 模拟我们手动登录服务器 输入cmd命令等操作 最后封装成自己的工具 xff0c 方便后面调用 目录 一 安装paramiko 二
  • Vim编辑器常用快捷方式

    这几天在学习shell编程 xff0c 其中常常会用到Linux下的vim编译器 xff0c 今天就总结一些在vim编辑器中常用的快捷键 xff0c 方便我们更好的使用 目录 一 vi编辑器基本概念 二 模式切换 三 编辑模式 四 命令行模
  • Linux面试相关知识点看着一文就够了

    今天和大家分享一下linux操作系统下主要用到的几个知识点 xff0c 分别是 xff1a linux目录结构 linux常用命令 文件权限操作 服务操作 yum安装命令 docker服务 vim编译器 pymysql测试连接 用户及组命令
  • Python对象比较及深浅拷贝

    今天和大家分享一个python语言中特别重要的一个知识点 xff0c 比较及拷贝 目录 一 61 61 和 is 二 深浅拷贝 2 1 浅拷贝 2 2 深拷贝 三 总结 一 61 61 和 is 等于 61 61 和is是Python中对象
  • python中的值传递和引用传递

    今天和大家分享python中很重要的一个知识点 xff1a 参数传递 xff0c 其中包括值传递和引用传递 目录 一 为什么要熟悉值传递和引用传递 1 1 值传递 1 2 引用传递 二 Python变量及其赋值 三 Python函数的参数传
  • MySQL8.0下DATE,DATETIME和TIMESTAMP的自动初始化和更新

    MySQL8 0下DATE DATETIME和TIMESTAMP的自动初始化和更新 DATE日期类型DATETIME和TIMESTAMP的不同什么是时区自动变动 xff1f DATETIME和TIMESTAMP的相同点微秒小数部分自动初始化
  • Python爬虫实战分析

    今天看到特别好的一篇文章 xff0c 分享给大家 从头到尾看了一遍 xff0c 以实战的例子分析爬虫所需要用到的知识点 十分受益 真可谓 xff1a python万能模板 xff0c 有了这个模板 xff0c 想爬取什么内容 xff0c 根
  • ansible dns

    1 详细叙述ansible的工作原理 工作原理 xff1a ansible是基于Python开发 xff0c 集合众多运维工具的优势 xff0c 实现批量的部署操作 xff0c ansible是基于模块化 xff0c 本身并没有部署能力 x
  • pip 安装命令 及 配置Path路径

    pip 不是内部或外部命令 也不是可运行的程序 或批处理文件 pip 安装命令 及 配置环境变量 numpy 输入pip install numpy 时 xff0c 提示 以numpy 为例 pip 不是内部或外部命令 也不是可运行的程序
  • 1-python工厂模式

    文章目录 工厂模式定义 xff1a 它的优点 xff1a 可以有如下三种实现方式1 简单工厂模式2 工厂方法模式3 抽象工厂模式总结 工厂模式定义 xff1a 在面向对象编程中 xff0c 术语 工厂 表示一个负责创建替他类型对象的类 通常
  • Facebook_Pop的使用指北

    背景 最近公司有了一个创新项目 xff0c 就是在视频视图之上添加一层视图 xff0c 视图设计涉及到了复杂的控件动画 xff0c 会根据视频的播放 xff0c 显示一些控件 xff0c 控件有位移 缩放 旋转 shake等动画 在网上调研
  • iOS Jenkins自动化打包 上传fir、蒲公英、邮件、钉钉提醒

    一 环境配置 注意 xff0c 本文章是以Jenkins2 263 4为例 1 首先安装Java环境 xff1a 官网下载地址 2 安装Jenkins 建议下载Jenkins 2 263 4版本 xff0c 因为最新版本存在login ke
  • iOS11 WKWebview App Crash闪退

    最近项目在iOS11 0 3 iOS11 1 2 iOS11 2 1 iOS 11 2 2 iOS11 2 6上面莫名其妙会崩溃 xff0c 本以为是block或者是设置User Agent导致的 xff0c 最后定位是Request设置u
  • iOS判断是否开启代理,防止Charles抓包

    直接检查是否设置了代理即可 BOOL checkProxySetting NSDictionary proxySettings 61 bridgeNSDictionary CFNetworkCopySystemProxySettings N
  • iOS 已有项目利用Pod集成RN

    一 背景 对于已经存在的iOS项目 xff0c 以模块化引入 xff0c OC与RN混编怎么做呢 xff1f 我们可以利用cocopods来集成 xff0c 直接使用pod install就可以让其他同事也快速集成 由于RN用npx rea