本文主要依赖我写的两个工具git
1.UCRuntimeKit:这个小工具主要是为了可以利用字符串+runtime
动态的调用方法.通过了500多条单元测试,基本知足全部的使用场景,安全,且支持向调用方抛出error,但不会crash.在这里它主要是为了向各个组件中的delegate转发多参数方法用的.github
2.UCAppDelegateReduce.这个小工具依赖上面的UCRuntimeKit
来作消息转发.swift
1.先将项目中的delegate与框架中的UCAppDelegateRealize
实现的22个方法进行交换,若是appdelegate没实现这个方法则不会交换,交换完成后不影响以前的逻辑,依旧会先调用原先appdelegate的逻辑,若是这22个方法没有包含你须要转发给组件的方法的话支持扩展.缓存
2.当delegate接收到调用时,会自动来到UCAppDelegateRealize
,这里在会根据位移枚举的配置来对各个组件调用,这个调用过程依赖UCRuntimeKit
,十分安全,不会crash.安全
能够利用cocoapod进行导入,pod 'UCAppDelegateReduce'
app
ObjcDemo框架
1.新建一个Objc类,例如我这里取名叫AppDelegateExchange
异步
2.在load类方法里进行下面的配置,就能够了工具
+ (void)load {
UCAppDelegateMethodExchangeManager *manager = [UCAppDelegateMethodExchangeManager share];
// sendMessageType 是位移枚举,能够选择本身想给子模块派发的方法
UCAppDelegateConfigModel *model1 = [[UCAppDelegateConfigModel alloc] initWithModuleName:@"UCObjcModule1AppDelegate" sendMessageType:didFinishLaunchingWithOptions];
UCAppDelegateConfigModel *model2 = [[UCAppDelegateConfigModel alloc] initWithModuleName:@"UCObjcModule2AppDelegate" sendMessageType:handleOpenURL | didFinishLaunchingWithOptions];
[manager startExchangeMethodWithOriginalAppDelegateName:@"UCAppDelegate" newModuleAppDelegateConfigArray:@[model1, model2]];
}
复制代码
SwiftDemo单元测试
1.新建一个Objc类,例如我这里取名叫AppDelegateExchange
2.要转发的Module中的appdelegate方法前要加@objc
,不然不支持动态调用
3.在load类方法里进行下面的配置,就能够了
+ (void)load {
UCAppDelegateMethodExchangeManager *manager = [UCAppDelegateMethodExchangeManager share];
// 这里Objc调用Swift须要加上相似命名空间的前缀,不然找不到这个Swift class
NSString *swiftModule1Name = [UCMediatorParameterParser getObjcClassName:@"SwiftModule1AppDelegate"];
// 支持位移枚举
UCAppDelegateConfigModel *model1 = [[UCAppDelegateConfigModel alloc] initWithModuleName:swiftModule1Name sendMessageType:didFinishLaunchingWithOptions];
NSString *swiftModule2Name = [UCMediatorParameterParser getObjcClassName:@"SwiftModule2AppDelegate"];
UCAppDelegateConfigModel *model2 = [[UCAppDelegateConfigModel alloc] initWithModuleName:swiftModule2Name sendMessageType:handleOpenURL | didFinishLaunchingWithOptions];
NSString *originalDelegateName = [UCMediatorParameterParser getObjcClassName:@"AppDelegate"];
[manager startExchangeMethodWithOriginalAppDelegateName:originalDelegateName newModuleAppDelegateConfigArray:@[model1, model2]];
}
复制代码
UCAppDelegateConfigModel
是很灵活的,支持位移枚举配置,配置后不会调用未配置的方法,另外manager的配置在app的生命周期中只应该在最开始load的时候配置一次!配置完成后这里会解析,生成相似这样的map,以代理方法名为key,须要转发的类名集合为value,并将这个map缓存在内存中,方便快速转发给各个组件.
这样你就能够把例如原先写在appdelegate中的开屏配置,分享key配置,支付配置,push路由配置,3Dtouch等等直接写在各自的模块中了,这里的调用顺序也是能够经过配置来决定的.
可是若是这个调用是异步的,例如组件B的一个功能依赖组件B的回调,建议仍是把这个写在组件a的delegate实现里.
作完了这些你会发现你原来的delegate基本能够什么都不写了,他已经把业务分散到各个组件中去了.
关于单元测试,这里基本只是测试了调用这个模块的,转发各个模块都是手动测得,判断参数能传入到各个组件就没有更深度的写了,这里的单元测试确实不太好写.