由于近期迭代周期变长,有时间想想代码持续改进的问题,再加上各业务模块代码从去年杂乱无章的状态,到目前整体结构基本清晰,进而想到了模块之间解耦的问题,于是有了本文,关于iOS组件化的一些思路及最终的解决方案。
技术界如今已存在很多关于组件化的解决方案,Class-Protocol、Target-Action等等,无论采用哪种方案,大家的目的都是为了解决代码庞大到一定规模时,依旧可以比较方便的进行管理和开发。这个时候就需要对各个业务模块进行梳理,在代码层面实现高内聚、低耦合,降低它们相互之间的变化带来的影响,从而提升开发效率。
先来看看如下两个图,对比一下:
从图中可以看出,在经过中间层框架跳转分发之后,各业务模块之间不存在引用关系,代码相互隔离,调用层次清晰,实现了模块间的真正解耦,完美的过渡到组件化的流程。
这里采用的是openURL: 和 openWithMapKey:的两种调用方式,以便实现App之间跳转及模块之间的跳转操作,具体采用哪种方式之后会讲到,下面来看一下中间层框架 JCNavigator 简单的调用过程:
接下来详细介绍下流程中出现的方法及相关类:
NSString
数据类型的赋值NSString
数据类型的赋值NSString
、NSArray
、UIImage
等系统数据类型及自定义数据类型的赋值总结:两种调用方法各有优势,通过推送、Widget、第三方App等外部入口打开你的App执行跳转操作时,建议使用openURL:,其他情况的跳转都采用openWithMapKey:的调用方式。
从上图可以看出,模块间无论是通过 openURL: 还是 openWithMapKey: 方法,都是找到对应的JCModuleMap
,然后实现最终的页面跳转。接下来看看如何通过JCModuleMap
实现这一操作:
总结:openURL: 通过NSURL及子类化JCModuleMap
中实现的mapKeyPrefix拼接对应的mapKey,然后和 openWithMapKey: 一样,都是通过classesForMapKeys方法,获取class-mapKey的映射关系,进而跳转到module中对应class的视图控制器页面。
属性名-属性值
生成字典传参:JCModuleMap
子类化实现的方法设置:好了,在实现JCModuleMap
子类化及相关跳转配置之后,现在最关键的操作来了,如何为各个modules之间提供通信及调用的接口,才能最大限度的解决解耦的问题?废话不多说,先来看看这段代码:
JCNavigator
类别;
2)在JCNavigator
类别中实现load类方法,添加对应子类化JCModuleMap
对象;
3)JCNavigator
类别头文件中提供统一的对外接口,实现文件中封装内部调用细节,从而解决modules之间的耦合问题。对于组件化的介绍,到这里接近尾声,整个解决方案有优点也有缺点,需要开发者各自权衡:
JCNavigator
中间层框架;
4)可实现Modules之间解耦、互不依赖;
5)无需额外处理Modules页面间的层级关系。JCModuleMap
,并将实例化对象添加到JCNavigator
,增加了内存消耗;
2)如果viewController类名或传递的参数发生改变,Xcode不会报错也没有警告,需及时维护子类化JCModuleMap的实现,并更新JCNavigator类别中的调用代码。