Ich finde es unmöglich, Kerndaten mit SwiftUI zu verwenden, da die Navigationslinkansicht beim Übergeben von Kerndaten an eine beobachtete Objektvariable der Ansicht auch nach dem Verschwinden der Ansicht einen Verweis auf das Objekt enthält, sobald ich die lösche Objekt aus dem Kontext Die App stürzt ab, ohne Fehlermeldungen.
Ich habe dies bestätigt, indem ich die Variable des Kerndatenobjekts optional in ein Ansichtsmodell eingeschlossen und das Objekt direkt nach der Aktion zum Löschen des Kontexts auf Null gesetzt habe und die App einwandfrei funktioniert. Dies ist jedoch keine Lösung, da ich das Kerndatenobjekt benötige an die schnellen ui-ansichten zu binden und die quelle der wahrheit zu sein. Wie soll das funktionieren? Ich kann mit SwiftUI anscheinend nichts aus der Ferne komplex machen.
Ich habe versucht, das übergebene Kerndatenobjekt einem optionalen @State zuzuweisen, aber dies funktioniert nicht. Ich kann @Binding nicht verwenden, da es sich um ein abgerufenes Objekt handelt. Und ich kann keine Variable verwenden, da Swiftui-Steuerelemente Bindungen erfordern. Es ist nur sinnvoll, ein @ObservedObject zu verwenden, aber dies kann nicht optional sein. Wenn das ihm zugewiesene Objekt gelöscht wird, stürzt die App ab, da ich es nicht auf Null setzen kann.
Hier ist das Kerndatenobjekt, das standardmäßig ein beobachtbares Objekt ist:
class Entry: NSManagedObject, Identifiable {
@NSManaged public var date: Date
}
Hier ist eine Ansicht, die ein Kerndateneingabeobjekt an eine andere Ansicht übergibt.
struct JournalView: View {
@Environment(\.managedObjectContext) private var context
@FetchRequest(
entity: Entry.entity(),
sortDescriptors: [],
predicate: nil,
animation: .default
) var entries: FetchedResults<Entry>
var body: some View {
NavigationView {
List {
ForEach(entries.indices) { index in
NavigationLink(destination: EntryView(entry: self.entries[index])) {
Text("Entry")
}
}.onDelete { indexSet in
for index in indexSet {
self.context.delete(self.entries[index])
}
}
}
}
}
}
Hier ist die Ansicht, die auf alle Attribute des übergebenen Kerndateneingabeobjekts zugreift. Einmal lösche ich diesen Eintrag aus jeder Ansicht, auf die hier übrigens immer noch verwiesen wird, und führt zum sofortigen Absturz der App. Ich glaube, dies hat auch etwas damit zu tun, dass der Navigationslink alle Zielansichten initialisiert, bevor überhaupt auf sie zugegriffen wird. Was keinen Sinn macht, warum es das tun würde. Ist das ein Fehler oder gibt es einen besseren Weg, dies zu erreichen?
Ich habe sogar versucht, das Löschen onDisappear ohne Erfolg durchzuführen. Selbst wenn ich das Löschen aus der JournalView durchführe, stürzt es immer noch ab, da der NavigationLink immer noch auf das Objekt verweist. Interessanterweise stürzt es nicht ab, wenn ein Navigationslink gelöscht wird, auf den noch nicht geklickt wurde.
struct EntryView: View {
@Environment(\.managedObjectContext) private var context
@Environment(\.presentationMode) private var presentationMode
@ObservedObject var entry: Entry
var body: some View {
Form {
DatePicker(selection: $entry.date) {
Text("Date")
}
Button(action: {
self.context.delete(self.entry)
self.presentationMode.wrappedValue.dismiss()
}) {
Text("Delete")
}
}
}
}
AKTUALISIEREN
Der Absturz führt mich zur ersten Verwendung des Eintrags in der EntryView und lautet Thread 1: EXC_BAD_INSTRUCTION (Code = EXC_I386_INVOP, Subcode = 0x0). Dies ist die einzige Nachricht, die ausgelöst wird.
Die einzige Möglichkeit, die ich mir vorstellen kann, besteht darin, dem Kerndatenobjekt "isDeleted" eine Eigenschaft hinzuzufügen und diese auf "true" zu setzen, anstatt zu versuchen, sie aus dem Kontext zu löschen. Wenn die App beendet wird oder gestartet wird, kann ich alle Einträge löschen und löschen, die gelöscht werden. Nicht ideal und würde es vorziehen, herauszufinden, was hier falsch ist, da ich anscheinend nichts anderes mache als das MasterDetailApp-Beispiel, das zu funktionieren scheint.
Antworten:
Ich hatte im Grunde das gleiche Problem. Es scheint, dass SwiftUI jede Ansicht sofort lädt, sodass die Ansicht mit den Eigenschaften des vorhandenen CoreData-Objekts geladen wurde. Wenn Sie es in der Ansicht löschen, in der über @ObservedObject auf einige Daten zugegriffen wird, stürzt es ab.
Meine Problemumgehung:
Sie müssen einen Notification.name definieren, wie:
Ein bisschen hacky, aber das funktioniert bei mir.
quelle
Ich bin auf dasselbe Problem gestoßen und habe keine Lösung für das Grundproblem gefunden. Aber jetzt "schütze" ich die Ansicht, die die referenzierten Daten verwendet, wie folgt:
Das fühlt sich auch hackig an, funktioniert aber vorerst gut. Es ist weniger komplex als die Verwendung einer Benachrichtigung, um das Löschen zu verschieben, aber dank sTOOs Antwort auf den Hinweis mit
.isFault
!quelle