CoreData Save not refreshing ListView SwiftUI



我有下面的代码,不确定为什么在单击保存并取消模式弹出时列表视图没有刷新。

Content View具有以下代码,该代码以模式调用NewFlightView。

Button {
//Show Modal New Flight Window
isPresented = true

} label: {
ZStack {
Circle ()
.foregroundColor(.white)
.frame(width: 50, height: 50)
.shadow(radius: 4)
Image(systemName: "plus.circle.fill")
.resizable()
.foregroundColor(.cyan)
.frame(width: 45, height: 45)
}
.offset(y: -15)
}
.buttonStyle(TabButtonStyle())
.sheet(isPresented: $isPresented, onDismiss: {
flightListVM.getAllFlights()
}, content: {
NewFlightView()
})
.onAppear(perform: {
flightListVM.getAllFlights()
})

NewFlightView是一个简单的输入视图,如

struct NewFlightView: View {
@StateObject private var newFlightVM = NewFlightViewModel()
@State private var isPresented: Bool = false
@Environment(.presentationMode) var presetationMode
var body: some View {
Form {
DatePicker("Flight Date", selection: $newFlightVM.date)
Spacer()
TextField("Enter origin airport", text: $newFlightVM.origin)
.textFieldStyle(.roundedBorder)
TextField("Enter destination airport", text: $newFlightVM.destination)
.textFieldStyle(.roundedBorder)
TextField("Enter altitude", value: $newFlightVM.altitude, format: .number)
.textFieldStyle(.roundedBorder)
.padding()

TextField("Enter flight duration", value: $newFlightVM.duration, format: .number)
.textFieldStyle(.roundedBorder)
.padding()

Button ("Save / Get Dose") {
newFlightVM.save()
presetationMode.wrappedValue.dismiss()
}
Spacer()
}
.navigationTitle("New Flight")

}
}

下面的ListView显示了航班添加到CoreData后的情况。

struct FlightsListView: View {
@StateObject private var flightListVM = FlightListViewModel()
@State private var isPresented: Bool = false
@AppStorage("isDarkMode") private var isDarkMode: Bool = false
@State private var isShowingSettings: Bool = false
@State private var isShowingAddNewFlight: Bool = false
@State private var animatingButton: Bool = false
@State var activeSheet: ActiveSheet?
// @ObservedObject private var appSetting = AppSetting.shared
private func deleteFlight(at indexSet: IndexSet) {
indexSet.forEach { index in
let flight = flightListVM.flights[index]
//delete the flight
flightListVM.deleteFlight(flight: flight)

//get all flights
flightListVM.getAllFlights()
}
}
var body: some View {
//Displays all flights in the database
List {
ForEach(flightListVM.flights, id: .id) { flight in
NavigationLink(destination: FlightDetailView(flight: flight )) {
FlightCell(flight: flight)
} //: Link

}.onDelete(perform: deleteFlight)
}
.listStyle(PlainListStyle())
.navigationTitle("Flights")

.sheet(isPresented: $isPresented, onDismiss: {
flightListVM.getAllFlights()
}, content: {
NewFlightView()
})

.onAppear {
flightListVM.getAllFlights()
}
}
} 

最后是我用来控制MVVM端的ViewModels。

NewFlightViewModel

class NewFlightViewModel: ObservableObject {
var date: Date = Date()
var origin: String = ""
var destination: String = ""
var altitude: Double = 0.0
var duration: Double = 0.0
func save() {

let manager = CoreDataManager.shared
let flight = Flight(context: manager.persistentContainer.viewContext)

flight.date = date
flight.origin = origin
flight.destination = destination
flight.altitude = altitude
flight.duration = duration

manager.save()

}
}

FlightListViewModel

class FlightListViewModel: ObservableObject {
@Published var flights = [FlightViewModel]()
func deleteFlight(flight: FlightViewModel) {
let flight = CoreDataManager.shared.getFlightById(id: flight.id)
if let flight = flight {
CoreDataManager.shared.deleteFlight(flight)
}
}
func getAllFlights () {

let flights = CoreDataManager.shared.getAllFlights()
DispatchQueue.main.async {
self.flights = flights.map(FlightViewModel.init)
} 
}
}

struct FlightViewModel {
let flight: Flight
var id: NSManagedObjectID {
return flight.objectID
}
var date: String? {
return flight.date?.asFormattedString()
}
var origin: String {
return flight.origin ?? ""
}
var destination: String {
return flight.destination ?? ""
}
var altitude: Double? {
return Double(flight.altitude)
}
var duration: Double? {
return Double(flight.duration)
}
}

好的。我需要一些指导,说明为什么在驳回模型NewFlightView时,它会触发ContentView的onDismiss句柄。如何刷新FlightListView而不必单击另一个选项卡,然后返回到Flights选项卡,从而触发其onAppear事件?

删除视图模型对象(我们在SwiftUI中不使用MVVM(并使用@FetchRequest。当结果发生变化时,它将自动调用body

将助手移动到NSManagedObjectContext的扩展,并通过@Environment(.managedObjectContext) var viewContextView结构中使用它。

在我看来,你好像错过了航班的NSManagedObject文件。在模型编辑器中生成,选择编辑器->创建NSManagedObject子类。选择Codegen类别/扩展。将您的计算属性放在那里,但不要进行任何必须在正文中进行的格式化,否则当区域设置更改时,SwiftUI将无法更新UILabels。

最新更新