SwiftUI中ViewModel的@Published数组父视图未同步更新问题如何解决
问题根因
你当前的两个视图各自初始化了独立的ViewModel实例,二者没有任何关联,子视图修改的是自己创建的ViewModel的属性,父视图的ViewModel自然收不到更新:
CreateOrderView中用@ObservedObject var vwModel = ViewModel()创建了第一个实例A- 子视图
ListView中用@StateObject var vwModel = ViewModel()创建了第二个实例B
你在子视图操作的是实例B的options,父视图的实例A的options一直是空数组,所以打印为空。
解决方案
核心是让父子视图共享同一个ViewModel实例,修改代码如下:
1. 修改父视图CreateOrderView的ViewModel声明
父视图作为ViewModel的持有者,要用@StateObject修饰(负责管理ViewModel的生命周期,避免视图重绘时实例被销毁重建):
struct CreateOrderView: View { // 改成@StateObject,作为ViewModel的持有者 @StateObject var vwModel = ViewModel() var body: some View { // 把当前持有的ViewModel传给子视图 ListView(vwModel: vwModel) Button(action: { print(vwModel.options) // 此时就能拿到子视图更新后的数组 vwModel.addCart() }, label: { Text("Add") .frame(maxWidth: .infinity, minHeight: 60) .background(Color.red) }) } }
2. 修改子视图ListView的ViewModel声明
子视图不要自己创建ViewModel,改成接收外部传入的实例即可:
struct ListView: View{ // 改成@ObservedObject,只接收外部传入的实例,不自己初始化 @ObservedObject var vwModel: ViewModel var body: some View { List(vwModel.options) {row in // 原有展示逻辑不变 print(vwModel.options) // 正常打印元素 } } }
扩展说明
如果你的视图层级很深,逐层传ViewModel比较麻烦,也可以用environmentObject的方式注入:
- 在父视图的外层调用处添加
.environmentObject(vwModel) - 子视图中用
@EnvironmentObject var vwModel: ViewModel声明即可,不需要手动传参。
内容的提问来源于stack exchange,提问作者Honey
相关产品推荐
相关产品推荐

