iOS 组件化方案对比

主流方案优缺点

路由 URL 统跳方案

使用路由URL统跳方案的优势是动态性及多端统一 (H5, iOS,Android,Weex/RN); 缺点是能处理的交互场景偏简单。所以一般更适用于简单 UI 页面跳转。一些复杂操作和数据传输,虽然也可以通过此方式实现,但都不是很效率。

服务注册方案

即每个模块提供自己对外服务的协议声明,然后将此声明注册到中间层。调用方能从中间层看到存在哪些服务接口,然后直接调用即可。

这种方式的优势也包括调用简单方便。代码自动补全和编译时检查都有效。实现起来也简单,协议的所有实现仍然在模块内部,所以不需要写反射代码了。同时对外暴露的只有协议,符合团队协作的“面向协议编程”的思想。劣势是如果服务提供方和使用方依赖的是公共模块中的同一份协议(protocol), 当协议内容改变时,会存在所有服务依赖模块编译失败的风险。同时需要一个注册过程,将 Protocol 协议与具体实现绑定起来。

业界里,蘑菇街的 ServiceManager 和阿里的 BeeHive 都是采用的这个方案。

基于反射的远程调用封装

但这种方式存在大量的 hardcode 字符串。无法触发代码自动补全,容易出现拼写错误,而且这类错误只能在运行时触发相关方法后才能发现。无论是开发效率还是开发质量都有较大的影响

这种方案的优势是调用简单方便,代码自动补全和编译时检查都仍然有效。 劣势是 category 存在重名覆盖的风险,需要通过开发规范以及一些检查机制来规避。同时 Mediator 只是收敛了 hardcode, 并未消除 hardcode, 仍然对开发效率有一定影响。

业界的 CTMediator 开源库,以及美团都是采用类似方案。

模块输出

每个业务模块的产出包括可执行文件和资源文件两部分。有2种选择:

  • 生成 framework
  • 生成静态库 + 资源 bundle.

使用framework的优点是输出在同一个对象内,方便管理。还能避免主程序文件过大, 导致启动速度变慢, 可以通过动态库懒加载来优化启动速度.
缺点是作为动态库载入,影响加载速度(启动阶段动态加载也会耗时, 但可以延后)。
另外如果使用framework,需要注意资源读取的问题。因为传统的资源读取方式无法定位到framework内资源,需要通过 bundleForClass: 才行。

总结

路由 优点 缺点 业界代表
url-scheme 1.通用,iOS/Android/Web2.服务器可动态配置页面跳转组件通信 1. 参数需集中文档维护;2.无法传递oc对象模型3.大量硬编码,需要注册scheme规则 JLRoutes 蘑菇街MGJRouter
protocol-class 1.基于协议,有严格的参数检查2.无硬编码 1. 需要协议管理中心,所有协议暴露2. 需要注册协议 阿里BeeHive
target-action 1.基于runtime,无需注册2.扩展性好 1. 参数以dictionary形式传递,存在一定的硬编码,且无法校验参数 CTMediator

路由方案-实现

protocol-class-service

  1. 基于协议,编译期严格检查接口调用参数正确
  2. 代码健壮性、可维护性
  3. 使用service实现

路由方案-如何解决协议的注册?

关键是把protocol和实现的class关联起来

  1. Load方法注册
  2. attribute(section(“data”))
    1. 编译期把protocol和对应的实现class字符串保存在data数据段中
    2. 运行期app读取数据段,执行注册协议
  3. 配置表注册
    1. 从配置表中读取需要注册的protocol-class映射关系,执行注册
    2. 配置表可以打入安装包,或者动态下发

路由方案-问题

遇到的问题

  1. protocol文件增多,协议管理中心的膨胀
    1. 控制模块划分粒度
  2. 数据模型多个模块随意使用
    1. 抽取基础数据模型model下沉
    2. 新增category存放与业务相关数据

参考文档

iOS 组件化 —— 路由设计思路分析
BeeHive —— 一个优雅但还在完善中的解耦框架

-------------本文结束感谢您的阅读-------------

欢迎关注我的其它发布渠道