如果你已经读到 iOS 架构系列这里,所有选项都摆在面前了:MVC、MVVM、MVP、VIPER、Clean Architecture、MV,以及 TCA。
但最难的问题仍然存在。“所以我们的 App 应该用哪个?”
“没有正确答案,只有取舍”这句话没错,但仅凭它仍然无法做决定。作为系列最后一篇,今天我们整理出真正可用于决策的具体标准。
标准 1:团队规模——架构是人的问题
首先,应根据人数而不是代码量来匹配架构的重量。
如果是1~2 人团队,速度比结构统一更重要。使用 SwiftUI 时,MV(Model–View)加 Repository 就够了;使用 UIKit 时,将页面跳转和网络部分从 MVC 中分离出来也足够。在这种规模下引入 VIPER(View、Interactor、Presenter、Entity、Router)或 TCA(The Composable Architecture),很容易让结构维护占用功能开发时间。
从3~10 人团队开始,团队需要就“逻辑在哪里”达成共识。MVVM + UseCase/Repository 是这一阶段稳妥的标准。每个页面保持相同结构,可以降低代码审查和新人上手成本。
如果是10 人以上、多个 squad,统一性和模块边界最优先。这一阶段通常会按功能模块化并加入 Clean Architecture 分层;如果状态复杂度高,也可以选择将 TCA 作为标准。VIPER 和 RIBs 实际被采用,也正是这类规模的组织。
标准 2:App 寿命——寿命越长,越要投资边界
为短命 App(原型、验证用 MVP(Minimum Viable Product)、活动 App)搭建分层是浪费。因为目标就是快速开发、快速学习。
如果是预计运行 3 年以上的产品,情况就不同了。期间服务器 API 会改版,设计会重做,也会经历 UIKit→SwiftUI 这样的框架迁移。真正有价值的不是华丽的模式,而是边界,例如隐藏数据来源的 Repository,以及承载业务规则的 UseCase。有边界就能局部替换,没有就只能全面重写。
标准 3:状态复杂度——唯一能证明采用 TCA 合理的轴
如果 App 大多只是“从服务器获取数据、展示数据,再把输入发送回服务器”,MVVM/MV 就够了。反过来,如果多个页面同时编辑同一状态,或实时同步、离线合并、复杂 undo 交织在一起,那么 TCA 强制控制状态变更路径的成本才开始合理。
正如上一篇所总结的,TCA 不是错误的选择,而是昂贵的选择。如果这一轴的复杂度不高,就无法收回这笔成本。
一页总结
| 情况 | 推荐 |
|---|---|
| 个人·原型 | MV(SwiftUI)或 MVC + 最少分离 |
| 小团队·普通服务 App | MVVM + Repository(需要时加入 UseCase) |
| 旧 UIKit·引入绑定的负担较大 | MVP + Coordinator |
| 大型组织·长期运行的产品 | Clean Architecture 分层 + 按功能模块化 |
| 状态复杂度高的领域 | TCA(前提是团队投入学习) |
比表格更重要的是:**无论从哪个格子开始,之后都可以移动到相邻格子。**但要做到这一点,需要一个条件。
无论选择什么,都必须遵守的不变量
贯穿整个系列的原则,可以压缩为一句话:
不要让 View 直接接触网络和数据库,并把业务规则放在页面代码之外。
只要遵守这一不变量,从 MVC 迁移到 MVVM,再从 MVVM 迁移到 TCA,就能将问题缩小为“替换页面层”。反之,如果这一点被破坏,无论采用哪种流行架构,最终都会全面重写。架构名称会留在简历上,但真正拯救产品的是边界。
最后,架构迁移的标准做法不是大爆炸式重写,而是从新页面开始渐进式迁移。仅仅因为流行就重做运行良好的旧页面,大多会以悔恨告终。
系列完结
把八篇文章各压缩成一句话,就是这样。
- MVC:理解责任集中在 UIViewController 中的结构,是起点
- MVVM:抽离页面状态并通过绑定同步;没有绑定就只完成了一半
- MVP vs MVVM:区别在于中间对象是否了解 View
- VIPER:将分离推向极致;其遗产由 Coordinator 和 UseCase 延续
- Clean Architecture:依赖只能向内,先从 Repository 开始
- TCA:在复杂度足以证明成本合理时,控制状态变更路径
- MV 之争:本质不在名称,而在逻辑的位置和依赖方向
- 选择指南:根据团队规模、App 寿命和状态复杂度选择,遵守不变量并渐进迁移
架构不是目的地,而是工具。投资于边界,让团队和 App 成长后仍能切换架构。

![[iOS 架构 #8] iOS 架构选择指南 封面图](/assets/images/posts/3dfe56b5-14ec-4e0a-846d-2d128e15798e/1.jpg)