Observation|创建 ViewModel 实例的最佳实践
了解如何在 SwiftUI 中管理 ViewModel 实例,适配 Observation 框架与新架构变更。

Combine(iOS 16 及以前)
在 Combine 框架中,通常使用 @StateObject
在 View 中创建 ViewModel 实例。
ViewModel 实例的生命周期:
@State
跟随 View@StateObject
独立管理,View 重建时保持
以上,是很好的实践方案。
Observation(iOS 17 及以后)
但在 Observation 框架中,不再能使用 @StateObject
,苹果建议使用基本的 @State
。
@State 的问题
如果在 View 组件中,直接使用使用 @State
创建 ViewModel 实例,很会导致 ViewModel 实例在预期之外的重复创建与销毁。

实际情况很复杂,并不是每次 View 更新都会导致 ViewModel 重建。例如如果有多个 View 使用同一个 ViewModel(例如 SummaryView 和 DetailView),就会导致同时存在多个 ViewModel 实例。还有其他一些情况,我也尚未完全弄明白。
但总的来说,使用 @State
确实会导致 ViewModel 实例难以管理的问题。因此,我需要尝试不同的方案来使用 ViewModel。
方案一 在 App 初始化并注入环境(苹果推荐)
这种方式是 Apple 推荐的方式,保留了优秀的可测试性。并且在 WWDC 实例项目中,也是这样做。
但就像我在下面这篇文章中所探讨的,这种用法在实际项目中会带来一些问题,例如:
- 难以在 View 组件之外访问实例
- 可能导致 App 文件中创建过多实例,导致管理困难。
方案二 使用单例模式
修改为使用单例之后,没有再出现重复实例的问题:

使用 Protocols 统一接口
用 Protocols 来统一 ViewModel 的接口设计,是 Apple 推荐的做法。
使用 Protocol 提供默认防抖功能
[ ] 待补充