返回顶部
首页 > 资讯 > 服务器 >iOS 组件化的三种方案
  • 616
分享到

iOS 组件化的三种方案

前端iosobjective-c中间件 2023-09-17 18:09:58 616人浏览 泡泡鱼
摘要

组件化 本文主要介绍iOS组件化的三种方案 1、常⽤的三种方案 URL SchemeTarget - ActionProtocol - Class 匹配 1.1、 URL Scheme路由 使 URL 处理本地的跳转通过中间层进⾏注册 &

组件化

本文主要介绍iOS组件化的三种方案


1、常⽤的三种方案

  • URL Scheme
  • Target - Action
  • Protocol - Class 匹配

1.1、 URL Scheme路由

  • 使 URL 处理本地的跳转
  • 通过中间层进⾏注册 & 调⽤ (load方法里把被调用者注册到中间层)
  • 注册表⽆需使用反射
  • 非懒加载 / 注册表的维护 / 参数

URL Scheme路由示例 

//MTMediator.h --- starttypedef void(^MTMediatorProcessBlock)(NSDictionary *params);+ (void)registerScheme:(NSString *)scheme processBlock:(MTMediatorProcessBlock)processBlock;+ (void)openUrl:(NSString *)url params:(NSDictionary *)params;//MTMediator.h --- end//MTMediator.m --- start+ (NSMutableDictionary *)mediatorCache{    static NSMutableDictionary *cacheScheme;    static dispatch_once_t onceToken;    dispatch_once(&onceToken, ^{        cacheScheme = @{}.mutableCopy;    });    return cacheScheme;}+ (void)registerScheme:(NSString *)scheme processBlock:(MTMediatorProcessBlock)processBlock{    if (scheme.length > 0 && processBlock) {        [[[self class] mediatorCache] setObject:processBlock forKey:scheme];    }}+ (void)openUrl:(NSString *)url params:(NSDictionary *)params{    MTMediatorProcessBlock block = [[[self class] mediatorCache] objectForKey:url];    if (block) {        block(params);    }}//MTMediator.m --- end//注册 --- start+ (void)load {    [MTMediator reGISterScheme:@"detail://" processBlock:^(NSDictionary * _Nonnull params) {        NSString *url = (NSString *)[params objectForKey:@"url"];        UINavigationController *navigationController = (UINavigationController *)[params objectForKey:@"controller"];        MTDetailViewController *controller = [[MTDetailViewController alloc] initWithUrlString:url];//        controller.title = [NSString stringWithFORMat:@"%@", @(indexPath.row)];        [navigationController pushViewController:controller animated:YES];    }];}//注册 --- end//调用 --- start//URL Scheme[MTMediator openUrl:@"detail://" params:@{@"url":item.articleUrl,@"controller":self.navigationController}];//调用 --- end复制代码
  • 参考了系统URL Scheme机制
  • 参数传递通过dictionary,对调用者不透明

目前iOS上大部分路由工具都是基于URL 进行匹配的,或者命名约定,通过runtime方法进行动态调用

优点:实现简单

缺点:需要维护字符串表,依赖于命名约定,无法在编译时暴露出所有问题,需要在运行时才能发现错误。

MGJRouter

URL路由方式主要是以蘑菇街为代表的的MGJRouter

实现原理:

  • App启动时实例化各组件模块,然后这些组件向ModuleManager注册Url,有些时候不需要实例化,使用class注册
  • 当组件A需要调用组件B时,向ModuleManager传递URL,参数跟随URL以GET方式传递,类似openURL。然后由ModuleManager负责调度组件B,最后完成任务。
// 1、注册某个URLMGJRouter.registerURLPattern("app://home") { (info) in    print("info: (info)")}//2、调用路由MGJRouter.openURL("app://home")复制代码

URL 路由的优点

  • 极高的动态性,适合经常开展运营活动的app
  • 方便地统一管理多平台的路由规则
  • 易于适配URL Scheme,可以下发

URl 路由的缺点

  • 传参方式有限,并且无法利用编译器进行参数类型检查,因此所有的参数都是通过字符串转换而来
  • 只适用于界面模块,不适用于通用模块
  • 参数的格式不明确,是个灵活的 dictionary,也需要有个地方可以查参数格式。
  • 不支持storyboard
  • 依赖于字符串硬编码,难以管理,蘑菇街做了个后台专门管理。
  • 无法保证所使用的的模块一定存在
  • 解耦能力有限,url 的”注册”、”实现”、”使用”必须用相同的字符规则,一旦任何一方做出修改都会导致其他方的代码失效,并且重构难度大

1.2、Target - Action

  • 抽离业务逻辑
  • 通过中间层进行调⽤
  • 中间层使⽤ runtime 反射
  • 中间层代码优化

Target - Action示例 

//MTMediator.h#import #import NS_ASSUME_NONNULL_BEGIN@interface MTMediator : NSObject//target action+ ( __kindof UIViewController *)detailViewControllerWithUrl:(NSString *)detailUrl;@endNS_ASSUME_NONNULL_END//MTMediator.m#import "MTMediator.h"@implementation MTMediator+ ( __kindof UIViewController *)detailViewControllerWithUrl:(NSString *)detailUrl{    Class detailVC = NSClassFromString(@"MTDetailViewController");    UIViewController *controller = [[detailVC alloc] performSelector:NSSelectorFromString(@"initWithUrlString:") withObject:detailUrl];    return controller;}@end//调用 //Target - Action UIViewController *vc = [MTMediator detailViewControllerWithUrl:item.articleUrl]; vc.title = @"详情啊"; [self.navigationController pushViewController:vc animated:YES];复制代码
  • 硬编码方式(直接调用,不利于维护和扩展)
  • perform 最多能传递2个参数,可以传入字典避免参数过多
  • initWithUrlString:方法必须实现 否则找不到sel崩溃
  • 业务逻辑柔合在Mediator中,可以各个模块写各自的MTMediator扩展

CTMediator

原理是通过oc的runtime、cateGory特性动态获取模块,例如通过NSClassFromString获取类并创建实例,通过performSelector + NSInvocation动态调用方法。

实现原理:

  • 1、利用分类为路由添加新接口,在接口中通过字符串获取对应的类
  • 2、通过runtime创建实例,动态调用实例的方法

CTMediator使用

//******* 1、分类定义新接口extension CTMediator{    @objc func A_showHome()->UIViewController?{        //在swift中使用时,需要传入对应项目的target名称,否则会找不到视图控制器        let params = [            kCTMediatorParamsKeySwiftTargetModuleName: "CJLBase_Example"        ]        //CTMediator提供的performTarget:action:params:shouldCacheTarget:方法 通过传入name,找到对应的targer和action        if let vc = self.performTarget("A", action: "Extension_HomeViewController", params: params, shouldCacheTarget: false) as? UIViewController{            return vc        }        return nil    }}//******* 2、模块提供者提供target-action的调用方式(对外需要加上public关键字)class Target_A: NSObject {    @objc func Action_Extension_HomeViewController(_ params: [String: Any])->UIViewController{        let home = HomeViewController()        return home    }}//******* 3、使用if let vc = CTMediator.sharedInstance().A_showHome() {            self.navigationController?.pushViewController(vc, animated: true)        }复制代码

模块间的关系:

模块A——Mediator——target——模块B

优点

  • 1、利用接口调用,实现了参数传递时的类型安全
  • 2、直接使用模块的protocol接口,无需再重复封装

缺点

  • 1、用框架来创建所有对象,创建方式不同,即不支持外部传入参数
  • 2、用OC runtime创建对象,不支持swift
  • 3、只做了protocol 和 class 的匹配,不支持更复杂的创建方式 和依赖注入
  • 4、无法保证所使用的protocol 一定存在对应的模块,也无法直接判断某个protocol是否能用于获取模块

1.2、Protocol - Class

  • 增加 Protocol Wrapper层 (中间件先注册Protocol和Class对应关系,将protocol和对应的进行字典匹配
  • 中间件返回 Protocol 对应的 Class,然后动态创建实例
  • 解决硬编码的问题

Protocol - Class示例

//具体的Protocol//MTMediator.h --- start@protocol MTDetailViewControllerProtocol + (__kindof UIViewController *)detailViewControllerWithUrl:(NSString *)detailUrl;@end@interface MTMediator : NSObject+ (void)registerProtol:(Protocol *)protocol class:(Class)cls;+ (Class)classForProtocol:(Protocol *)protocol;@end//MTMediator.h --- end//MTMediator.m --- start+ (void)registerProtol:(Protocol *)protocol class:(Class)cls{    if (protocol && cls) {        [[[self class] mediatorCache] setObject:cls forKey:NSStringFromProtocol(protocol)];    }}+ (Class)classForProtocol:(Protocol *)protocol{    return [[[self class] mediatorCache] objectForKey:NSStringFromProtocol(protocol)];}//MTMediator.m --- end//被调用//MTDetailViewController.h --- start@protocol MTDetailViewControllerProtocol;@interface MTDetailViewController : UIViewController@end//MTDetailViewController.h --- end//MTDetailViewController.m --- start+ (void)load {    [MTMediator registerProtol: @protocol(MTDetailViewControllerProtocol) class:[self class]];}#pragma mark - MTDetailViewControllerProtocol+ ( __kindof UIViewController *)detailViewControllerWithUrl:(NSString *)detailUrl{    return [[MTDetailViewController alloc]initWithUrlString:detailUrl];}//MTDetailViewController.m --- end//调用Class cls = [MTMediator classForProtocol: @protocol(MTDetailViewControllerProtocol)];if ([cls respondsToSelector: @selector(detailViewControllerWithUrl:)]) {        [self.navigationController pushViewController:[cls detailViewControllerWithUrl:item.articleUrl] animated:YES];}复制代码
  • 被调用者先在中间件注册Protocol和Class对应关系,对外只暴漏Protocol

BeeHive

protocol比较典型的三方框架就是阿里的BeeHiveBeeHive借鉴了spring Service、Apache DSO的架构理念,采用aop+扩展App生命周期api形式,将业务功能基础功能模块以模块方式以解决大型应用中的复杂问题,并让模块之间以Service形式调用,将复杂问题切分,以AOP方式模块化服务。

BeeHive 核心思想

  • 1、各个模块间调用从直接调用对应模块,变成调用Service的形式,避免了直接依赖。
  • 2、App生命周期的分发,将耦合在AppDelegate中逻辑拆分,每个模块以微应用的形式独立存在。

示例如下:

//******** 1、注册[[BeeHive shareInstance] registerService:@protocol(HomeServiceProtocol) service:[BHViewController class]];//******** 2、使用#import "BHService.h"id< HomeServiceProtocol > homeVc = [[BeeHive shareInstance] createService:@protocol(HomeServiceProtocol)];复制代码

优点

  • 1、利用接口调用,实现了参数传递时的类型安全
  • 2、直接使用模块的protocol接口,无需再重复封装

缺点

  • 1、用框架来创建所有对象,创建方式不同,即不支持外部传入参数
  • 2、用OC runtime创建对象,不支持swift
  • 3、只做了protocol 和 class 的匹配,不支持更复杂的创建方式 和依赖注入
  • 4、无法保证所使用的protocol 一定存在对应的模块,也无法直接判断某个protocol是否能用于获取模块

建议:URL Scheme - handler 配合 Protocol - Class 使用
 

附带:iOS组件化方案架构设计


​​​​​​​

 

来源地址:https://blog.csdn.net/yezuiqingxin/article/details/126018623

--结束END--

本文标题: iOS 组件化的三种方案

本文链接: https://lsjlt.com/news/411271.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • iOS 组件化的三种方案
    组件化 本文主要介绍iOS组件化的三种方案 1、常⽤的三种方案 URL SchemeTarget - ActionProtocol - Class 匹配 1.1、 URL Scheme路由 使 URL 处理本地的跳转通过中间层进⾏注册 &...
    99+
    2023-09-17
    前端 ios objective-c 中间件
  • 数组的三种初始化方式
    1. 直接初始化:在声明数组的同时给出初始值,例如:`int[] arr = {1, 2, 3, 4, 5};` 这种方式适用于已知...
    99+
    2023-09-01
    数组
  • Java实现监听文件变化的三种方案详解
    目录背景方案一:定时任务 + File#lastModified方案二:WatchService方案三:Apache Commons-IO小结背景 在研究规则引擎时,如果规则以文件的...
    99+
    2024-04-02
  • ios组件化开发的方法是什么
    iOS组件化开发的方法有很多种,以下是其中几种常用的方法:1. CocoaPods:使用CocoaPods可以方便地管理项目中的各个...
    99+
    2023-08-15
    ios
  • Node.js编写组件的三种实现方式
    首先介绍使用v8 API跟使用swig框架的不同: (1)v8 API方式为官方提供的原生方法,功能强大而完善,缺点是需要熟悉v8 API,编写起来比较麻烦,是js强相关的,不容易支持其它脚本语言。 (2)...
    99+
    2022-06-04
    三种 组件 方式
  • Vue父子组件传值的三种方法
    目录前言一、Vue父子传值的方法二、方法详解1.props / $emit2.$parent / children3.$ref总结提示:文章写完后,目录可以自动生成,如何生成可参考右...
    99+
    2022-12-20
    Vue父子组件传值 Vue父子组件
  • 详解iOS设置字体的三种方式
    有时候项目需要显示一些非系统的字体达到一些UI的效果,目前设置字体有三种方式,默认方式、bundle方式,coreText方式。 1 默认方式 这种方式就是正常的字体设置方式 l...
    99+
    2022-05-22
    ios 字体
  • iOS组件化源码分析
    这篇“iOS组件化源码分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“iOS组件化源码分析”文章吧。一、iOS 组件化常用...
    99+
    2023-07-05
  • react三种定义组件方法是什么
    这篇文章主要介绍“react三种定义组件方法是什么”,在日常操作中,相信很多人在react三种定义组件方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”react三种定...
    99+
    2024-04-02
  • Vue组件通信传递数据的三种方式
    目录Vue传值传递数据的三种方式方式一方式二方式三Vue传值 Vue.js是一个组件化的前端开发框架,支持父子组件之间的消息传递和数据通信。子组件向父组件传递消息的过程称为&ldqu...
    99+
    2023-05-17
    Vue组件通信几种方式 Vue组件通信实现
  • 关于Redis数据库三种持久化方案介绍
    目录一、回顾Redis二、方案一:bgsave三、方案二:配置文件rdb四、方案三:aof总结一、回顾Redis 1、redis的特点 redis是一个内存中的数据结构存储系统。优点...
    99+
    2024-04-02
  • java声明数组的三种方式
    Java声明数组的三种方式有:1. 静态声明:使用静态初始化方式声明数组,即在声明数组的同时,给数组元素赋初值。例如:int[] a...
    99+
    2023-08-28
    java
  • iOS组件化开发实战记录
    目录1. 组件化需求来源2. 组件化初识3. 组件化必备的工具使用5. 组件工程兼容swift环境6. 组件之间的通讯7. 组件化后的资源加载8. OC工程底层换swift代码9. ...
    99+
    2022-05-25
    ios 组件化 开发
  • React路由组件传参的三种方式(params、search、state)
    目录向路由组件传递params参数向路由组件传递search参数向路由组件传递state参数总结三种向路由组件传参的方式向路由组件传递params参数 当点击消息1这个导航链接时,展...
    99+
    2024-04-02
  • React组件间通信的三种方法(简单易用)
    目录一、父子组件通信二、跨级组件通信1、逐层传值2、跨级传值三、兄弟(无嵌套)组件通信四、路由传值五、Redux  React知识中一个主要内容便是组件之间的通信,以下列举...
    99+
    2024-04-02
  • React组件的三种写法是什么
    这篇文章将为大家详细讲解有关React组件的三种写法是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。React 专注于 view 层,组件化则是 React 的基础,...
    99+
    2024-04-02
  • 三种Node.js写文件的方式
    本文分享了Node.js写文件的三种方式,具体内容和如下 1、通过管道流写文件   采用管道传输二进制流,可以实现自动管理流,可写流不必当心可读流流的过快而崩溃,适合大小文件传输(推荐) var re...
    99+
    2022-06-04
    三种 方式 文件
  • 详解IOS判断当前网络状态的三种方法
    在项目中,为了好的用户体验,有些场景必须线判断网络状态,然后才能决定该干嘛。比如视频播放,需要线判断是Wifi还是4G,Wifi直接播放,4G先提示用户。获取网络状态的方法大概有三种...
    99+
    2022-05-21
    IOS 网络状态 wifi 2g 3g 4g
  • 一文掌握Redis的三种集群方案
    在开发测试环境中,我们一般搭建Redis的单实例来应对开发测试需求,但是在生产环境,如果对可用性、可靠性要求较高,则需要引入Redis的集群方案。虽然现在各大云平台有提供缓存服务可以直接使用,但了解一下其背后的实现与原理总还是有些...
    99+
    2021-08-29
    一文掌握Redis的三种集群方案
  • sql跨表查询的三种方案总结
    目录前言方案一:连接多个库,同步执行查询优点缺点代码执行方案二:在主数据库增加冗余表,通过定时更新,造成同库联表查询优点缺点相似实现场景方案三:dbLink本地连接多个库,在本地进行数据分析优点缺点前言 最近又个朋友问我...
    99+
    2022-08-11
    sql跨表查询方案 sql跨表查询
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作