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

SwiftUI视图不更新求助:已用@Published与@ObservedObject

问题分析与解决方案

嘿,我一眼就揪出问题的根源啦!你现在遇到的HomeView不更新的核心问题,是你在AddView和HomeView里分别创建了完全独立的AddViewModel实例——简单说就是,AddView里往自己的viewModel数组加狗,HomeView的viewModel根本没收到这个变化,当然不会更新UI咯!

问题拆解

你看:

  • 在AddView里你写了@ObservedObject var viewModel = AddViewModel()
  • 在HomeView里又写了@ObservedObject var viewModel = AddViewModel()

这两行代码会生成两个毫无关联的AddViewModel对象,就像两个不同的文件夹,你往A文件夹里放文件,B文件夹当然不会自动出现这个文件啦!

解决方案:共享同一个ViewModel实例

我们需要让AddView和HomeView共用同一个AddViewModel对象,这里推荐两种常用方式:

方式一:使用EnvironmentObject(最适合全局共享场景)

  1. 在App入口注入ViewModel
    找到你的App主文件(比如YourDogApp.swift),初始化ViewModel并把它注入到整个App的环境中:

    @main
    struct YourDogApp: App {
        // 只在这里初始化一次ViewModel
        private let addViewModel = AddViewModel()
        
        var body: some Scene {
            WindowGroup {
                HomeView()
                    .environmentObject(addViewModel) // 注入到环境
            }
        }
    }
    
  2. 在View中获取共享的ViewModel

    • 修改HomeView,去掉自己初始化的代码,改用@EnvironmentObject获取:
      struct HomeView: View { 
          @EnvironmentObject var viewModel: AddViewModel 
          
          var body: some View { 
              ScrollView { 
                  VStack { 
                      ForEach(viewModel.dogs) { dog in 
                          CardView(dog: dog)
                          Text(dog.name)
                      } 
                  } 
              } 
          } 
      }
      
    • 修改AddView,同样改用@EnvironmentObject获取:
      struct AddView: View {
          @EnvironmentObject var viewModel: AddViewModel 
          // 去掉原来的@ObservedObject var viewModel = AddViewModel()
          
          // 你的其他属性(name、selectedRace等)和UI代码...
          
          .navigationBarItems(trailing: Button("Publish") { 
              viewModel.dogs.append(Dog(name: self.name, race: races[selectedRace], age: self.age, gender: genders[selectedGender], sterile: self.isSterile, pictureURL: "", location: "", dogFriendly: self.isDogFriendly, catFriendly: self.isCatFriendly, childFriendly: self.isChildFriendly, needsGarden: self.needsGarden, isClean: self.isClean)) 
              print(viewModel.dogs) 
          })
      }
      

方式二:父视图传递ViewModel(适合局部共享场景)

如果你的ViewModel只需要在HomeView和它导航的AddView之间共享,也可以直接传递:

  1. HomeView持有ViewModel
    struct HomeView: View { 
        @ObservedObject var viewModel = AddViewModel() 
        
        var body: some View { 
            NavigationStack { // 或者NavigationView,看你的SwiftUI版本
                ScrollView { 
                    VStack { 
                        ForEach(viewModel.dogs) { dog in 
                            CardView(dog: dog)
                            Text(dog.name)
                        } 
                    } 
                }
                .navigationDestination(for: AddView.self) {
                    AddView(viewModel: viewModel) // 传递同一个ViewModel实例
                }
            }
        } 
    }
    
  2. AddView接收传递的ViewModel
    struct AddView: View {
        @ObservedObject var viewModel: AddViewModel // 不再自己初始化
        
        // 你的其他属性和UI代码...
        
        .navigationBarItems(trailing: Button("Publish") { 
            viewModel.dogs.append(/* 你的Dog实例 */)
        })
    }
    

额外提醒

不管用哪种方式,核心都是保证所有需要响应数据变化的View,绑定的是同一个ViewModel实例。另外,你的Dog结构体已经是Identifiable的,ForEach可以正常遍历,这部分没问题~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 11:07:43