一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第17天,点击查看活动详情。
URL
路由
URL
路由的方案相对简单,基于URL
匹配,双方进行命名约定,使用Runtime
方法进行动态调用
方案的代表框架:MGJRouter
最基本的使用
[MGJRouter registerURLPattern:@"mgj://foo/bar" toHandler:^(NSDictionary *routerParameters) {
NSLog(@"routerParameterUserInfo:%@", routerParameters[MGJRouterParameterUserInfo]);
}];
[MGJRouter openURL:@"mgj://foo/bar"];
当匹配到URL
后,routerParameters
会自带几个key
extern NSString *const MGJRouterParameterURL;
extern NSString *const MGJRouterParameterCompletion;
extern NSString *const MGJRouterParameterUserInfo;
方案的思路:
App
启动时实例化各组件模块,这些组件向ModuleManager
注册URL
。不需要实例化的组件,可使用Class
进行注册- 当
组件A
调用组件B
时,向ModuleManager
传递URL
,可携带参数。使用封装的openURL
方法,由ModuleManager
负责组件B
的调度
优点:
- 动态性高,适合页面和参数自由度较高的电商类
App
- 多平台的路由规则可统一管理
- 适用于
URL Scheme
缺点:
- 使用字符串传递,安全性和稳健性难以保证,被使用的模块不一定存在
- 对于字符串的管理成本较高
- 不支持
storyboard
- 一旦使用该方案,很难被替换。对于整个工程来说,重构难度加大
target-action
基于OC
的Runtime
和Category
特性动态获取模块
- 通过
NSClassFromString
获取类并创建实例 - 通过
performSelector + NSInvocation
动态调用方法
方案的代表框架:CTMediator
最基本的使用
//1、创建CTMediator的分类,完成对外的接口
@implementation CTMediator (CTMediatorModuleAActions)
- (void)CTMediator_presentImage:(UIImage *)image
{
[self performTarget:@"A" action:@"nativePresentImage" params:@{@"image":image} shouldCacheTarget:NO];
}
@end
//2、添加Action,完成具体的业务
@implementation Target_A
- (id)Action_nativePresentImage:(NSDictionary *)params
{
DemoModuleADetailViewController *viewController = [[DemoModuleADetailViewController alloc] init];
viewController.valueLabel.text = @"this is image";
viewController.imageView.image = params[@"image"];
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:viewController animated:YES completion:nil];
return nil;
}
@end
//3、外部调用
[[CTMediator sharedInstance] CTMediator_presentImage:[UIImage imageNamed:@"image"]];
方案的思路:
- 组件的核心
CTMediator
类,使用字符串按照指定规则,拿到真实的target
和action
的名称 - 通过方法签名,判断返回值类型,如果是非
id
类型,使用NSInvocation
进行消息转发- 传入
target
、selector
、argument
- 使用
getReturnValue
方法将其返回
- 传入
- 否则,返回值
id
类型,直接使用performSelector
进行方法调用
优点:
- 利用分类将接口按业务拆分,去中心化
- 框架核心代码短小精悍,实现方式轻量
缺点:
- 每一个接口都需要中间方法,有些繁琐
- 用字符串传递,被使用的模块不一定存在
- 业务越复杂,创建的分类和
target-action
中间类就会越多
模块之间的通讯流程: