iOS 项目架构设计是指为应用程序构建一个合理的、可扩展的、易于维护的架构。这涉及到选择适当的技术和设计模式,以确保应用程序在不同阶段的开发和维护过程中能够高效地运行。

项目层级划分

以下是一个示例,在不同场景下可以根据项目的需要进行调整:

职责描述
4业务模块层模块化业务代码,如直播模块、私信模块等。
3业务服务层面向业务需求的数据封装层,例如项目内通用的UI组件、网络服务等。
2抽象服务层跨项目通用的面向协议的服务或通用组件。
1基础工具层包含第三方库以及跨项目通用的基础工具,如类扩展等。

依赖关系要保持单向线性:上层可以依赖下层,下层不可以依赖上层,同一层级内不可互相依赖。例如:

  • 第 4 层的模块可以依赖第 3、2、1 层的组件
  • 第 3 层的组件只可以依赖第 2、1 层的组件
  • 第 2 层的组件只可以依赖第 1 层的组件
  • 第 1 层的组件只可以依赖其它第三方库

第 4 层的一个组件连同其依赖的底层组件能够成为一个独立的模块,这样可以保证依赖链清晰且没有冗余。

模块间的解藕

前面实现了分层,但是如何处理模块与模块之间的通信呢?常用路由方案参考如下:

  • casatwy/CTMediator:基于消息传递的路由框架,它通过定义一组消息和对应的处理方法来实现页面之间的跳转和数据传递。简单易用,可以快速实现页面之间的跳转和数据传递,但是灵活性较差,不适合处理复杂的页面逻辑。
  • joeldev/JLRoutes:基于 URL 路由的框架,它通过解析 URL 来实现页面之间的跳转和数据传递。灵活性较高,可以处理复杂的页面逻辑,但是需要更多的代码来实现页面之间的跳转和数据传递。
  • SwiftUI/NavigationStack:SwiftUI 提供的一个路由框架,它通过视图栈和状态管理的方式实现页面之间的跳转和数据传递。简洁易用、可以处理复杂的页面逻辑;但是只能在 iOS 16 及以上版本中使用。

面向协议设计组件

组件内部避免为了实现某个功能而直接依赖具体的第三方库,例如一个本地资源远程化功能的组件,需要拿到一个链接,下载资源、解压、然后本地缓存并提供获取资源接口。

不推荐的做法 👎

直接依赖一个网络库和解压库(或实现下载和解压代码),内部实现完全部流程(下载、解压、后续处理)之后返回结果。

看似组件开箱即用,但是却为项目的维护性、扩展性埋下了坑。如果项目里已有网络库和解压库,那么直接使用它就会额外被迫导入组件A直接依赖的库。

推荐的做法 👍

声明一个 Downloader 协议:要求传入下载连接返回解压好的文件夹路径(异步)

组件A内部不关心如何下载以及解压,只知道 Downloader 协议的对象返回的结果就是解压好的文件夹路径,因此内部依然能够继续进行后续流程并返回结果。

调用层需要额外实现一下这个协议,如果项目里已有网络库和解压库,那么直接使用它就不会额外被迫导入组件A直接依赖的库。