SwiftUI中CoreData保存后ListView不刷新问题求助
SwiftUI+CoreData+MVVM列表不自动刷新问题解决
问题根源
核心问题是ContentView和FlightsListView各自创建了独立的FlightListViewModel实例:
- ContentView内的
flightListVM与FlightsListView内的flightListVM是两个完全独立的对象 - 关闭弹窗时ContentView的
onDismiss调用的是自身VM的getAllFlights(),不会同步到FlightsListView的VM数据,因此列表无法自动更新
解决方案
1. 共享ViewModel实例
在父层级(如ContentView或App)创建唯一的FlightListViewModel,再传递给FlightsListView,确保两个视图共用同一个VM:
修改ContentView代码
struct ContentView: View { @StateObject private var flightListVM = FlightListViewModel() // 全局唯一实例 @State private var isPresented = false var body: some View { TabView { // 将共享VM传递给FlightsListView FlightsListView(flightListVM: flightListVM) .tabItem { Image(systemName: "airplane") Text("Flights") } // 其他标签页代码... } .sheet(isPresented: $isPresented, onDismiss: { // 调用共享VM的刷新方法 flightListVM.getAllFlights() }) { NewFlightView() } } }
修改FlightsListView代码
struct FlightsListView: View { // 改为@ObservedObject,接收外部传递的VM实例 @ObservedObject var flightListVM: FlightListViewModel @State private var isPresented: Bool = false private func deleteFlight(at indexSet: IndexSet) { indexSet.forEach { index in let flight = flightListVM.flights[index] flightListVM.deleteFlight(flight: flight) flightListVM.getAllFlights() } } var body: some View { List { ForEach(flightListVM.flights, id: \.id) { flight in NavigationLink(destination: FlightDetailView(flight: flight )) { FlightCell(flight: flight) } }.onDelete(perform: deleteFlight) } .listStyle(PlainListStyle()) .navigationTitle("Flights") .sheet(isPresented: $isPresented, onDismiss: { flightListVM.getAllFlights() }) { NewFlightView() } .onAppear { flightListVM.getAllFlights() } } }
2. 进阶优化:自动监听CoreData数据变化
手动调用getAllFlights()不够优雅,可利用CoreData的监听机制,让ViewModel自动感知数据变化并更新列表,彻底摆脱手动刷新:
修改FlightListViewModel代码
import Combine import CoreData class FlightListViewModel: ObservableObject { @Published var flights = [FlightViewModel]() private var cancellables = Set<AnyCancellable>() init() { // 创建Flight实体的查询请求 let fetchRequest: NSFetchRequest<Flight> = Flight.fetchRequest() // 按日期倒序排列(可选配置) fetchRequest.sortDescriptors = [NSSortDescriptor(keyPath: \Flight.date, ascending: false)] // 监听CoreData上下文的查询结果变化,自动更新列表 CoreDataManager.shared.persistentContainer.viewContext .publisher(for: fetchRequest) .map { flights in flights.map(FlightViewModel.init) } .receive(on: DispatchQueue.main) .assign(to: \.flights, on: self) .store(in: &cancellables) } func deleteFlight(flight: FlightViewModel) { if let flight = CoreDataManager.shared.getFlightById(id: flight.id) { CoreDataManager.shared.deleteFlight(flight) } } // 不再需要getAllFlights()方法,数据变化时自动触发列表更新 }
修改后,无论是新增、删除还是修改Flight数据,列表都会自动刷新,无需手动调用刷新方法。
内容的提问来源于stack exchange,提问作者AVSoftware
相关产品推荐
相关产品推荐

