iOS 组件化的三种方案

组件化

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


1、常⽤的三种方案

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

1.1、 URL Scheme路由

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

URL Scheme路由示例 

//MTMediator.h --- start
typedef 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、注册某个URL
MGJRouter.registerURLPattern("app://home") { (info) inprint("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 <UIKit/UIKit.h>
#import <Foundation/Foundation.h>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 - ActionUIViewController *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和actionif 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 <NSObject>+ (__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<MTDetailViewControllerProtocol>
@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比较典型的三方框架就是阿里的BeeHive。BeeHive借鉴了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组件化方案架构设计图


​​​​​​​

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/1382003.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

《最强大模型平台上线,被很多行业“盯”上了》

千帆大模型 1、国内最多的模型2、国内最全的Prompt模板3、总结 千帆大模型平台是面向企业开发者的一站式大模型开发及服务运行平台&#xff0c;也是百度智能云推出的全球首个一站式企业级大模型平台。在提供全套文心大模型服务的基础上&#xff0c;还支持第三方开源大模型、各种…

【2020年底攻略】支付宝沾沾卡怎么获得 沾沾卡获取攻略分享

沾福气卡是支付宝中的一个特殊卡片&#xff0c;用这个新卡有机会复制朋友的任何一张卡牌&#xff0c;很多玩家不知道如何获取这张卡&#xff0c;下面来为大家带来的介绍。 沾福气卡怎么获得 1月28日-2月4日18点期间&#xff0c;每日手臂付款可以领取一张沾福气卡&#xff1b;…

2021支付宝集五福【攻略】!!!

一年一度的支付宝集五福在2月1号的凌晨开始了&#xff0c;虽然一年比一年瓜分的少&#xff0c;但不知不觉集福卡成了过年最佳的消遣娱乐方式了。活动从2月1日开始至1月11日结束。 零、额外福利 额外福卡二维码扫福器下载地址&#xff1a;https://syx0226.lanzous.com/iOP2Zl5w…

随机送一张花花卡跟一张敬业卡

马云的福字火了&#xff0c;猪肉铺大叔你也火了……马云福字是什么梗&#xff1f;之前马云曾写过一个福字&#xff0c;福中有田有猪有网有支付宝&#xff0c;昨天&#xff0c;有网友表示&#xff0c;一位菜市场的猪肉老板大叔对这个福字很中意&#xff0c;在店铺前挂出了这个福…

分割一切模型 Fast SAM C++推理部署---onnxruntime(有核心代码)

Fast SAM C推理部署—onnxruntime 核心源代码在结尾处 晓理紫 0 XX开局一张图&#xff0c;剩下… 本文记录只为日后更好学习 1 Fast SAM 简介 Fast SAM是仅使用SAM作者发布的SA-1B数据集的2%进行训练的CNN任意分割模型。FastSAM的性能与SAM方法相当&#xff0c;运行速度提高了…

支付宝五福53张自动领取程序 v2021

简介&#xff1a; 临近过年&#xff0c;身边的朋友们都开始参加支付宝一年一度的集五福活动了&#xff01;今天小编带来的这款支付宝五福53张自动领取程序能够帮助集福的朋友们更加轻松地完成任务&#xff0c;让用户一键完成53个任务并自动获取福卡&#xff0c;非常方便&#…

2920集五福_2020年支付宝集五福攻略

支付宝2020扫福活动在今天也就是1月13日开始啦&#xff0c;听说&#xff0c;居然有2.4万人集齐了吗&#xff0c;也太快了吧&#xff01;有人好奇&#xff0c;2020年支付宝集五福活动规则&#xff0c;有什么新玩法。不过不少小伙伴们比较关心的是2020每天可以扫几张福&#xff1…

2020 春节集五福最详细收集攻略

本文由葡萄城技术团队于博客原创并首发 转载请注明出处&#xff1a;葡萄城官网&#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务&#xff0c;赋能开发者。 一年一度的支付宝集五福活动已经开始了&#xff0c;不知从什么时候开始&#xff0c;集五福已经成为了惯例…

已有一万名快手用户集齐好运卡获得六六六早鸟红包,还可再分一亿

“谁要来沾幸运的吗&#xff01;我已经集齐了&#xff01;“ “天呐&#xff0c;马上就要到一万人&#xff01;谁能让我沾一沾幸运&#xff01;“ 伴随着超话里网友们热火朝天的讨论&#xff0c;快手「集好运中国福」活动也终于迎来了第1万个集齐五张好运卡的幸运用户。 据了…

支付宝集五福可以开“外挂”? 70万人秒集齐!

点击上方[全栈开发者社区]→右上角[...]→[设为星标⭐] 2月1日零点&#xff0c;2021年支付宝集五福活动正式开始&#xff0c;打响“年味”第一枪&#xff01; 我稍微看了看&#xff0c;今年的集福难度更低&#xff0c;生怕你集不全似的给各种“外挂”&#xff0c;开始13小时&am…

2021支付宝集五福最新最全攻略:万能福沾沾福敬业福

五福背后的 Web 3D 引擎 Oasis Engine 正式开源 五福还是一如既往&#xff0c;独乐乐不如众乐乐 分享一波攻略顺便晒晒我的会不会被打 骚套路 1. 敬业福套路 可以5个小朋友建个小群&#xff0c;分享套卡互相领取 2. 万能福套路 3. 沾沾福套路 分享福卡也有机会得沾沾 …

《Linux从练气到飞升》No.12 Linux进程概念

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的…

RT-Thread智能音箱音频应用实践

国内智能音箱的问世早于国外&#xff0c;但由于国内对智能化概念普及程度较低&#xff0c;初期智能音箱并没有受到很多关注。但近几年国内智能音箱行业经历了从百花齐放到三足鼎立的发展阶段&#xff0c;来自RT-Thread的黄天翔将从占据主流市场的三个厂商脱颖而出的秘诀开始&am…

智能音箱技术概览

目前的智能音箱多基于语音控制&#xff0c;其基本交互流程可以用图1 概括&#xff1a; 1&#xff09;用户通过自然语言向音箱提出服务请求或问题 2&#xff09;音箱拾取用户声音&#xff08;音箱本地完成&#xff09;并分析&#xff08;一般在服务器端完成&#xff09; 3&#…

揭秘智能音箱里那些神秘的声学技术

音箱行业有着悠久的历史&#xff0c;但是在过去十多年里&#xff0c;传统的音箱行业面临着极大的市场困境&#xff0c;例如蓝牙音箱刚出现各个厂商便直接杀成了一片红海。而2015年随着智能音箱的涌现&#xff0c;特别是亚马逊的Echo、京东的叮咚、阿里的小飞&#xff0c;不仅对…

智能家居控制系统MECOOL KA1智能音响

MECOOL KA1是智能音箱和4K安卓电视流媒体设备的结合。该设备采用Amlogic S905Y4 SoC四核ARM Cortex -A35处理器&#xff0c;支持远场语音和免提电视控制。 MECOOL KA1通过ART&#xff08;谷歌智能语音测试&#xff09; ART 旨在验证集成了 Google 助理的设备的助理功能。要被…

AI智能音箱五大功能中应用的数字功放芯片

AI智能音箱多基于语音控制&#xff0c;其基本交互流程可以用下图概括&#xff1a;1&#xff09;用户通过自然语言向音箱提出服务请求或问题 2&#xff09;音箱拾取用户声音&#xff08;音箱本地完成&#xff09;并分析&#xff08;一般在服务器端完成&#xff09;3&#xff09;…

Talk | ICCV‘23清华大学刘世隆:From Detection to Grounding-迈向更强的开集目标检测

本期为TechBeat人工智能社区第521期线上Talk&#xff01; 北京时间8月10日(周四)20:00&#xff0c;清华大学博士生—刘世隆的Talk已准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “From Detection to Grounding-迈向更强的开集目标检测”&#xff0c;他分…

5个PPT素材、模板网站,建议收藏~

做PPT绝对不能错过这5个网站&#xff0c;建议收藏~ 1、菜鸟图库 https://www.sucai999.com/search/ppt/0_0_0_1.html?vNTYxMjky 菜鸟图库素材非常齐全&#xff0c;设计、办公、图片、视频等素材这里都能找到&#xff0c;PPT模板数量很可观&#xff0c;模板样式多&#xff0c…

数据结构和算法——散列表的性能分析(开放地址法的查找性能、期望探测次数与装填因子的关系、分离链接法的查找性能)

目录 开放地址法的查找性能 线性探测法 平方探测法和双散列探测法 期望探测次数与装填因子的关系 分离链接法的查找性能 总结 散列表的性能分析 平均查找长度&#xff08;ASL&#xff09;用来度量散列表查找效率&#xff1a;成功、不成功关键词的比较次数&#xff0c;取…