SwiftUI关闭FavouriteView后HomeView无法更新ViewModel数据问题
问题根源
你遇到的核心问题是:HomeView和FavouriteView各自创建了独立的FavMenuViewModel实例。FavouriteView中更新的是自己持有的ViewModel数据,HomeView的ViewModel完全不受影响,因此返回后仍显示旧数据。
解决方案
要解决这个问题,核心是让两个视图共享同一个FavMenuViewModel实例,同时确保ViewModel的数据变化能自动通知视图刷新。
方案1:直接传递共享ViewModel(最直观)
步骤1:修改FavouriteView接收外部ViewModel
将FavouriteView中的@StateObject改为@ObservedObject,接收从HomeView传入的ViewModel:
struct FavouriteView: View { @Environment(\.dismiss) var dismiss @ObservedObject var favViewModel: FavMenuViewModel // 替换原@StateObject @State private var selectedItem: Int = 0 @State var selectedfavMenu: AllMenu? = nil // 剩余代码保持不变... }
步骤2:在HomeView中传递ViewModel给FavouriteView
修改navigationDestination的代码,把HomeView自己的ViewModel传过去:
.navigationDestination(isPresented: $gotoAddMore) { FavouriteView(showSideMenu: $showSideMenu, favViewModel: favViewModel) .toolbar(.hidden, for: .navigationBar) }
步骤3:优化HomeView的数据绑定
确保FavMenuViewModel中的favMenuList用@Published修饰(这是视图自动刷新的关键):
class FavMenuViewModel: ObservableObject { @Published var favMenuList: [AllMenu] = [] // 必须添加@Published func fetchFavList(completion: @escaping (Bool) -> Void) { // 原有的网络请求逻辑,请求完成后直接赋值favMenuList即可 } }
然后把HomeView中的@State private var favMenu改为计算属性,自动跟随ViewModel数据变化:
struct HomeView: View { @StateObject private var favViewModel = FavMenuViewModel() // 替换原@State变量为计算属性 private var favMenu: [AllMenu] { favViewModel.favMenuList.filter { $0.isSelected == true } } var body: some View { ZStack { VStack{ favView() } } .onAppear { favViewModel.fetchFavList { status in // 无需手动赋值favMenu,计算属性会自动更新 } } // 已修改的navigationDestination代码... // 剩余代码保持不变... } }
步骤4:调整FavouriteView的关闭时机
确保数据更新完成后再关闭页面,避免HomeView提前展示旧数据:
func updateFavoriteMenus() { // 原有的更新收藏接口请求代码 do { if let jsonResponse = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] { print("Response JSON: \(jsonResponse)") favViewModel.fetchFavList { status in print("updated fav menus.... \(favViewModel.favMenuList)") dismiss() // 数据更新完成后再关闭页面 } } } catch { print(error.localizedDescription) dismiss() // 错误场景也关闭页面 } }
方案2:使用环境对象(适合多视图共享场景)
如果项目中有多个视图需要使用这个ViewModel,推荐用环境注入的方式:
- 在App入口注入ViewModel:
@main struct YourApp: App { @StateObject private var favViewModel = FavMenuViewModel() var body: some Scene { WindowGroup { HomeView() .environmentObject(favViewModel) } } }
- 在
HomeView和FavouriteView中通过环境获取ViewModel:
// HomeView struct HomeView: View { @EnvironmentObject private var favViewModel: FavMenuViewModel private var favMenu: [AllMenu] { favViewModel.favMenuList.filter { $0.isSelected == true } } // 剩余代码... } // FavouriteView struct FavouriteView: View { @Environment(\.dismiss) var dismiss @EnvironmentObject private var favViewModel: FavMenuViewModel // 剩余代码... }
这种方式不需要手动传递参数,所有注入了环境的视图都能共享同一个ViewModel实例。
内容的提问来源于stack exchange,提问作者Swift
相关产品推荐
相关产品推荐

