You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 16:22:52