In SwiftUI Viewho Listbasato sulla @FetchRequestvisualizzazione dei dati di Primaryun'entità e l' Secondaryentità collegata tramite relazione . Il Viewe il suo Listviene aggiornato correttamente, quando aggiungo un nuovo Primarysoggetto con una nuova entità secondaria correlata.
Il problema è che quando aggiorno l' Secondaryelemento connesso in una vista di dettaglio, il database viene aggiornato, ma le modifiche non si riflettono Primarynell'elenco. Ovviamente, il @FetchRequestnon viene attivato dalle modifiche in un'altra vista.
Successivamente, quando aggiungo un nuovo elemento nella vista principale, l'elemento precedentemente modificato viene finalmente aggiornato.
Per ovviare al problema, aggiorno inoltre un attributo Primarydell'entità nella vista di dettaglio e le modifiche si propagano correttamente alla Primaryvista.
La mia domanda è: come posso forzare un aggiornamento su tutti i relativi @FetchRequestsdati core di SwiftUI? In particolare, quando non ho accesso diretto alle entità correlate / @Fetchrequests?
import SwiftUI
extension Primary: Identifiable {}
// Primary View
struct PrimaryListView: View {
@Environment(\.managedObjectContext) var context
@FetchRequest(
entity: Primary.entity(),
sortDescriptors: [NSSortDescriptor(key: "primaryName", ascending: true)]
)
var fetchedResults: FetchedResults<Primary>
var body: some View {
List {
ForEach(fetchedResults) { primary in
NavigationLink(destination: SecondaryView(primary: primary)) {
VStack(alignment: .leading) {
Text("\(primary.primaryName ?? "nil")")
Text("\(primary.secondary?.secondaryName ?? "nil")").font(.footnote).foregroundColor(.secondary)
}
}
}
}
.navigationBarTitle("Primary List")
.navigationBarItems(trailing:
Button(action: {self.addNewPrimary()} ) {
Image(systemName: "plus")
}
)
}
private func addNewPrimary() {
let newPrimary = Primary(context: context)
newPrimary.primaryName = "Primary created at \(Date())"
let newSecondary = Secondary(context: context)
newSecondary.secondaryName = "Secondary built at \(Date())"
newPrimary.secondary = newSecondary
try? context.save()
}
}
struct PrimaryListView_Previews: PreviewProvider {
static var previews: some View {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
return NavigationView {
PrimaryListView().environment(\.managedObjectContext, context)
}
}
}
// Detail View
struct SecondaryView: View {
@Environment(\.presentationMode) var presentationMode
var primary: Primary
@State private var newSecondaryName = ""
var body: some View {
VStack {
TextField("Secondary name:", text: $newSecondaryName)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
.onAppear {self.newSecondaryName = self.primary.secondary?.secondaryName ?? "no name"}
Button(action: {self.saveChanges()}) {
Text("Save")
}
.padding()
}
}
private func saveChanges() {
primary.secondary?.secondaryName = newSecondaryName
// TODO: ❌ workaround to trigger update on primary @FetchRequest
primary.managedObjectContext.refresh(primary, mergeChanges: true)
// primary.primaryName = primary.primaryName
try? primary.managedObjectContext?.save()
presentationMode.wrappedValue.dismiss()
}
}
ObservableObject?
