In einer SwiftUI habe Viewich eine Listbasierend auf @FetchRequestder Anzeige von Daten einer PrimaryEntität und der über eine Beziehung verbundenen SecondaryEntität. Das Viewund sein Listwird korrekt aktualisiert, wenn ich eine neue PrimaryEntität mit einer neuen verwandten sekundären Entität hinzufüge .
Das Problem ist, dass beim Aktualisieren des verbundenen SecondaryElements in einer Detailansicht die Datenbank aktualisiert wird, die Änderungen jedoch nicht in der PrimaryListe berücksichtigt werden. Offensichtlich wird das @FetchRequestnicht durch die Änderungen in einer anderen Ansicht ausgelöst.
Wenn ich danach ein neues Element in der Primäransicht hinzufüge, wird das zuvor geänderte Element endgültig aktualisiert.
Als Problemumgehung aktualisiere ich zusätzlich ein Attribut der PrimaryEntität in der Detailansicht und die Änderungen werden korrekt in die PrimaryAnsicht übertragen.
Meine Frage lautet: Wie kann ich ein Update für alle @FetchRequestsin SwiftUI Core Data verwandten Elemente erzwingen? Insbesondere, wenn ich keinen direkten Zugriff auf die zugehörigen Entitäten habe / @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?
