SwiftUI 5中如何在@Observable类中嵌套使用另一个@Observable类?
解决SwiftUI 5 Observation中@Observable类间引用的问题
错误原因
@Environment属性包装器仅适用于SwiftUI的View类型(结构体或类),不能直接在@Observable类中使用,这是你遇到致命错误的核心原因。
可行解决方案
1. 构造函数注入(推荐)
通过构造函数直接传入依赖的@Observable实例,这是最符合依赖注入原则的方式,便于单元测试和解耦:
@Observable class NotesViewModel { var notes: [Note] = [] let categoriesViewModel: CategoriesViewModel // 初始化时传入CategoriesViewModel实例 init(categoriesViewModel: CategoriesViewModel) { self.categoriesViewModel = categoriesViewModel } func foo(){ print(categoriesViewModel.categories.count) } }
在视图层注入时,先从环境中获取CategoriesViewModel,再初始化NotesViewModel并注入环境:
struct ContentView: View { @Environment(CategoriesViewModel.self) var categoriesVM var body: some View { YourChildView() .environment(NotesViewModel(categoriesViewModel: categoriesVM)) } }
2. 单例模式(适合简单场景)
如果CategoriesViewModel是全局唯一的实例,可以使用单例直接访问:
@Observable class CategoriesViewModel { static let shared = CategoriesViewModel() var categories: [Category] = [] } @Observable class NotesViewModel { var notes: [Note] = [] private let categoriesViewModel = CategoriesViewModel.shared func foo(){ print(categoriesViewModel.categories.count) } }
注意:单例会增加代码耦合度,不利于单元测试,仅建议在小型项目或简单场景中使用。
3. 依赖注入容器(适合复杂项目)
创建全局依赖容器统一管理所有@Observable实例,适合多ViewModel依赖复杂的大型项目:
// 依赖容器 class DIContainer { static let shared = DIContainer() // 初始化所有ViewModel实例 let categoriesViewModel = CategoriesViewModel() lazy var notesViewModel = NotesViewModel(categoriesViewModel: categoriesViewModel) } @Observable class NotesViewModel { var notes: [Note] = [] let categoriesViewModel: CategoriesViewModel init(categoriesViewModel: CategoriesViewModel) { self.categoriesViewModel = categoriesViewModel } func foo(){ print(categoriesViewModel.categories.count) } }
在视图层注入容器中的实例:
struct ContentView: View { var body: some View { YourChildView() .environment(DIContainer.shared.categoriesViewModel) .environment(DIContainer.shared.notesViewModel) } }
总结
优先选择构造函数注入,它能让代码更易于测试和维护;@Environment仅用于View层级的依赖传递,不能在@Observable类中直接使用。
内容的提问来源于stack exchange,提问作者Adel Bassiony
相关产品推荐
相关产品推荐

