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

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,推荐用环境注入的方式:

  1. 在App入口注入ViewModel:
@main
struct YourApp: App {
    @StateObject private var favViewModel = FavMenuViewModel()
    
    var body: some Scene {
        WindowGroup {
            HomeView()
                .environmentObject(favViewModel)
        }
    }
}
  1. 在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 00:56:01