其实之前写过这么一片相似的文章连接,利用字符串
+runtime
能作到命名域级别的解耦,其实这种作法很极端,编码也很硬核,并且数据的类型也比较难肯定,其实这也是Objc自己动态弱类型语言的缺点.git
作了蛮久的iOS了,我就在前面的文章基础上分析几点本身的心得吧,若有不合适的地方,能够指正哈.demo地址github
1.正常的业务模块,没什么好说的,能够写UI,业务逻辑,工具这样子的架构
2.AppDelegate在本模块中的一个接收类,负责去解耦主工程中杂糅的业务,例如分享组件能够把分享key注册等事件放到这个类中app
3.ActionService分类,至关于组件对外暴露的一个接口,咱们利用宏去规范它的命名,到时利用router去调用便可,这个架构的复杂点主要就在于如何去维护这么一个字符串常量列表,这里能够经过一些脚本扫描分类来减轻这个工做量.工具
UCACTION_SERVICE_EXTERN_METHOD(ModuleA, getVC, argu) {
return [ModuleAVC new];
}
复制代码
UCACTION_SERVICE_EXTERN_METHOD
这个宏主要是拼接组件名和方法名成为一个对象方法,起到规范命名的做用.组件化
1.router
,这里来负责派发方法能够这么调用UCROUTER_OPEN_NATIVE(ModuleA, getVC, nil)
,只要输入组件名,接口名便可,若是没参数的话不传就行.测试
2.AppDelegateExchange
这里负责交换我写的一个小工具UCAppDelegateReduce
和appDelegate
中的方法,而后听从自身的生命周期到各个组件的AppDelegate
实现中去,支持位移枚举配置,支持Swift
.编码
+ (void)load {
UCAppDelegateMethodExchangeManager *manager = [UCAppDelegateMethodExchangeManager share];
// sendMessageType 是位移枚举,能够选择本身想给子模块派发的方法
UCAppDelegateConfigModel *model1 = [[UCAppDelegateConfigModel alloc] initWithModuleName:@"ModuleAAppDelegate" sendMessageType:didFinishLaunchingWithOptions];
UCAppDelegateConfigModel *model2 = [[UCAppDelegateConfigModel alloc] initWithModuleName:@"ModuleBAppDelegate" sendMessageType:handleOpenURL | didFinishLaunchingWithOptions];
[manager startExchangeMethodWithOriginalAppDelegateName:@"AppDelegate" newModuleAppDelegateConfigArray:@[model1, model2]];
}
复制代码
3.ActionService
实际上是一个空类,每一个组件会实现他的一个分类用做一个对外接口的做用.spa
近期在拆主工程中的登陆模块,我是想作成那种正确依赖,不依赖runtime这样的解耦方式,只要导入组件,他会把全部依赖的组件进行导入,实现一个完整的功能这么一个作法,比较理想,今天才把他作出来.设计
其实新项目,新模块你作组件还好,尽可能少依赖外部,业务拆的清楚点基本还不算难作.拆老业务仍是很头大的,有不少不属于登陆模块的却还集成在登陆这个文件里,我也是醉了,算是个吐槽吧.你导入一个,他要是依赖不少的话你还得想办法去解决,这就是个恶性循环了,在这点上看这个命名域解耦虽然偷懒了,可是拆老项目组件仍是蛮好用的,我为了正确设计依赖把别的组件也改了很多,把不属于这个业务模块的全清掉了.如今也能作到导入登陆的话可以导入相关依赖的模块了,是个完整功能能够运行了.
我的仍是偏向于正确的设计依赖,不要偷懒,因此咱们在写项目的时候就要考虑好他的业务职责,尽可能保持模块职责单一,依赖尽可能保持纵向,若是横向依赖的话尽可能仍是用router
或者协议
去解决它.
另外不要为了组件化而去作组件化,能够把一些业务上或许可以复用的能够拆一下.
拆的话能够先从Service
层开始拆,好比分享,支付,map这些与业务牵扯比较小的,打下基石之后,拆业务也好拆一点.
最后这个AppDelegate
解耦的思路蛮不错的,他的动态派发通过了400多条的UT测试,仍是比较稳的,也比较好扩展,这点能够用用看.