SwiftUI中如何让父子ViewModel共享Item列表并同步视图更新?
解决SwiftUI父子ViewModel共享单一数据源的问题
要实现父子视图共享同一数据源、保证数据一致性且视图自动刷新,核心思路是让子ViewModel依赖父ViewModel的数据源,而非单独维护副本。以下是具体实现方案:
核心逻辑
- 子ViewModel不再独立持有
items数组,而是通过引用直接操作父ViewModel的数据源 - 父视图将自身ViewModel传递给子视图,子视图通过
@ObservedObject监听其变化 - 子ViewModel通过构造函数接收父ViewModel,封装添加Item的业务逻辑
修改后的完整代码
import SwiftUI struct ParentView: View { @StateObject private var viewModel = ViewModel() var body: some View { VStack { // 将父ViewModel传递给子视图 ChildView(parentViewModel: viewModel) Text("Items: \(viewModel.items.count)") } } } extension ParentView { @MainActor class ViewModel: ObservableObject { @Published var items: [Item] = [] // 模拟从API获取数据的方法 func fetchItems() async { // 替换为实际API请求逻辑 items = [Item(name: "初始数据")] } } } struct ChildView: View { // 接收外部传入的父ViewModel,用ObservedObject监听变化 @ObservedObject var parentViewModel: ParentView.ViewModel // 子ViewModel依赖父ViewModel初始化 @StateObject private var viewModel: ViewModel init(parentViewModel: ParentView.ViewModel) { self.parentViewModel = parentViewModel self._viewModel = StateObject(wrappedValue: ViewModel(parentViewModel: parentViewModel)) } var body: some View { List { // 直接使用父ViewModel的items数据源 ForEach(parentViewModel.items) { item in Text(item.name) } } .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button { viewModel.addItem() } label: { Label("添加Item", systemImage: "plus") } } } .task { // 初始化时调用父ViewModel的API请求方法 await parentViewModel.fetchItems() } } } extension ChildView { @MainActor class ViewModel: ObservableObject { private let parentViewModel: ParentView.ViewModel // 构造函数注入父ViewModel init(parentViewModel: ParentView.ViewModel) { self.parentViewModel = parentViewModel } func addItem() { // 直接操作父ViewModel的items数组,保证单一数据源 parentViewModel.items.append(Item(name: "新Item")) } } } // 让Item符合Identifiable协议,支持ForEach遍历 struct Item: Identifiable { let id = UUID() var name: String }
关键细节说明
- 单一数据源保障:所有对
items的增删改操作都直接作用于父ViewModel的数组,彻底避免数据不一致问题 - 自动视图刷新:父ViewModel的
items是@Published属性,任何修改都会触发父视图和子视图的自动刷新 - 职责分离:父ViewModel负责数据获取(API请求),子ViewModel负责添加Item的业务逻辑,符合MVVM的单一职责原则
- 依赖注入:子ViewModel通过构造函数接收父ViewModel,降低耦合度,也便于单元测试
内容的提问来源于stack exchange,提问作者Christoffer Reijer
相关产品推荐
相关产品推荐

