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
相关产品推荐
相关产品推荐

