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

SwiftUI 表单提交后前序列表未收到数据变更通知问题如何解决

根本原因

你当前的StockViewModel和LotEditViewModel是完全独立的两个实例,没有共享数据源的变更通知链路。模拟数据库数组更新后,StockViewModel持有的lots属性没有收到变更信号,因此不会触发SwiftUI视图重绘。
另外你当前代码存在一个常见误用:StockView中用@ObservedObject声明视图生命周期内需要持有的ViewModel是错误的,视图每次重绘都会重新初始化StockViewModel实例,进一步导致数据同步失效。

推荐解决方案

方案1:全局共享数据仓库(适合中大型项目,无页面耦合)

这是最符合SwiftUI数据流规范的实现:

  • 定义全局可观测的数据仓库,所有数据库操作都走这个单例:
class StockDataStore: ObservableObject {
    static let shared = StockDataStore()
    @Published var allLots: [Lot] = [] // 你的模拟数据库数组,用@Published修饰
    private init() {}
}
  • 在App入口将数据仓库注入环境:
@main
struct StockApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(StockDataStore.shared)
        }
    }
}
  • 修改StockViewModel,订阅数据仓库的变更:
class StockViewModel: ObservableObject {
    @Published var lots: [Lot] = []
    private var cancellables = Set<AnyCancellable>()
    let symbol: String
    
    init(_ symbol: String) {
        self.symbol = symbol
        // 订阅全局数据仓库的变更,自动过滤当前股票的手数数据
        StockDataStore.shared.$allLots
            .map { $0.filter { $0.symbol == symbol } }
            .assign(to: \.lots, on: self)
            .store(in: &cancellables)
    }
}
  • 编辑页的save方法直接修改StockDataStore.shared.allLots,修改后@Published会自动通知所有订阅者,列表页会自动刷新。
  • 同时修正StockView的ViewModel声明,用@StateObject保证ViewModel生命周期和视图绑定:
struct StockView: View {
    @StateObject var vm: StockViewModel
    init(_ symbol: String) {
        _vm = StateObject(wrappedValue: StockViewModel(symbol))
    }
    // 其余代码不变
}

方案2:回调闭包(适合小型项目,实现最轻量)

不需要改全局架构,仅通过页面回调触发数据刷新:

  • 给LotEditView新增保存成功回调参数:
struct LotEditView: View {
    @Environment(\.presentationMode) var mode
    @ObservedObject var vm: LotEditViewModel
    let onSave: () -> Void // 新增回调
    
    init(_ id: UUID, onSave: @escaping () -> Void) {
        vm = LotEditViewModel(id)
        self.onSave = onSave
    }
    
    var body: some View {
        VStack {
            Form {
                // 表单内容不变
            }
        }
        .navigationTitle("Edit Lot")
        .toolbar {
            Button("Done") {
                vm.save()
                onSave() // 保存后触发回调
                mode.wrappedValue.dismiss()
            }
        }
    }
}
  • 在StockView跳转时传入回调,触发数据重拉:
NavigationLink(destination: LotEditView(lot.id, onSave: {
    vm.fetchLots() // 调用你的ViewModel重新从数据库拉取数据的方法
})) {
    // 单元格内容不变
}

同时记得将StockView的@ObservedObject改为@StateObject,避免ViewModel重复初始化。

内容的提问来源于stack exchange,提问作者graem

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 15:15:03