Ich habe ein sehr seltsames Problem mit inversen Beziehungen in Core Data, und ich habe es geschafft, mein Problem auf ein minimales Beispiel zu reduzieren, ausgehend von einem neuen Projekt in xcode basierend auf der Fenstervorlage mit Unterstützung für Core Data sehr wenig dort).
Angenommen, wir haben ein Kerndatenmodell mit drei Entitäten: Abteilung, Mitarbeiter und AbteilungZusammenfassung (eine Art Entität, die einige Statistiken über die Abteilung darstellt). Der Einfachheit halber haben wir nur Eins-zu-Eins-Beziehungen:
%Vor% Das ist alles, was im Modell vorhanden ist. In application:didFinishLaunchingWithOptions:
erstellen wir einen Mitarbeiter und eine Abteilung und richten KVO ein:
Der Zweck des KVO-Handlers besteht darin, eine Zusammenfassung für die Abteilung zu erstellen, sobald die Abteilung des Mitarbeiters eingerichtet ist:
%Vor% createSummary
ist einfach: Es erstellt ein neues Zusammenfassungsobjekt und ordnet es der Abteilung zu, und überprüft dann, dass die umgekehrte Beziehung zwischen der Abteilung und dem Zusammenfassungsobjekt ebenfalls festgelegt ist :
Diese Bestätigung schlägt fehl. Wenn wir die Abteilungs- und Zusammenfassungsobjekte drucken, nachdem die Abteilung der Zusammenfassung festgelegt wurde, erhalten wir
%Vor%für die Zusammenfassung, wie erwartet, aber
%Vor% für die Abteilung (mit einer nil
Zusammenfassung). Wenn wir jedoch den Aufruf von createSummary
verzögern, damit er erst bei der nächsten Iteration des Runloops ausgeführt wird:
dann funktioniert alles wie erwartet.
Das Verzögern der -Assistenz hilft stattdessen nicht : Die umgekehrte Relation wird im Objektgraphen wirklich nicht gesetzt , obwohl sie gesetzt wird in der Datenbank (wenn Sie die Datenbank speichern und die App neu starten würden, erscheint plötzlich die umgekehrte Beziehung).
Ist das ein Fehler in Core Data? Ist das dokumentiertes Verhalten, das ich verpasst habe? Verwende ich Core Data auf eine Weise, die nicht beabsichtigt war?
Beachten Sie, dass der KVO-Handler aufgerufen wird, während Core Data (automatisch) ein (anderes) inverses festlegt: Wir setzen das employee
-Feld der Abteilung manuell, Core Data legt automatisch department
des Mitarbeiters fest. Feld, und das wiederum löst den KVO-Handler aus. Vielleicht ist das einfach zu viel für Core Data :) In der Tat, wenn wir
stattdessen funktioniert alles wieder wie erwartet.
Irgendwelche Hinweise würden geschätzt werden.
Dies ist ein klassisches Core Data Problem. Die Dokumente geben ausdrücklich an:
In der Praxis ist dies jedoch eine unausgegorene Lüge, da sie unzuverlässig ist.Da Core Data die Pflege der Objektdiagrammkonsistenz für Sie übernimmt, müssen Sie nur ein Ende einer Beziehung ändern und alle anderen Aspekte werden für Sie verwaltet.
Meine Antworten auf Ihre Fragen lauten also:
Ist das ein Fehler in Core Data?
JA.
Ist das dokumentiertes Verhalten, das ich verpasst habe?
Nein.
Verwende ich Kerndaten auf eine Weise, die nicht beabsichtigt war?
Nein.
Sie haben bereits die "richtige" Lösung für Ihr Problem bereitgestellt, die gleiche Lösung, die ich jedes Mal verwende, wenn ich Beziehungswerte in jeder einzelnen Core Data App ändere, die ich mache. Für buchstäblich Hunderte von Fällen ist das empfohlene Muster:
%Vor%dh, stellen Sie die Beziehung selbst umgekehrt ein, wenn Sie die Beziehung ändern.
Jemand hat vielleicht mehr Licht zu diesem Thema oder eine kanonische Form, um Ihr Problem zu lösen, aber meiner Erfahrung nach gibt es keine Möglichkeit zu garantieren, dass eine Beziehung aktiv ist, es sei denn, es wird manuell festgelegt (wie Ihr Problem zeigt) . Noch wichtiger ist, dass diese Lösung zwei weitere Vorteile bietet:
Der letzte Punkt ist kontraintuitiv. Auf der einen Seite scheint es den Code zu komplizieren und ihn länger zu machen, indem er Zeilen hinzufügt, die laut den Dokumenten ein kurzer Ein-Zeilen-Anruf sein könnten. Aber nach meiner Erfahrung ist es eine Rettung des Programmierers zum Core Data Editor, um Modellbeziehungen visuell zu suchen und zu bestätigen, was in der Zeit wertvoller ist. Es ist besser, klar und deutlich zu sein, anstatt ein mentales Modell dessen zu haben, was passieren sollte, wenn man eine Beziehung ändert.
Ich würde auch vorschlagen, NSmanagedObject eine einfache Kategorie hinzuzufügen:
%Vor%wie in:
%Vor%Es gibt einige Fälle, in denen diese Kategorie erweitert werden kann, aber ich würde zum Beispiel die Löschung auf eine andere Art und Weise durchführen.
Kurz gesagt: behandeln alle Ihre eigenen Beziehungen jedes Mal explizit. Core Data ist in dieser Hinsicht nicht vertrauenswürdig.
Wie wäre es mit dem Speichern des ManagedObjectContext direkt nach dem Einfügen?
Tags und Links objective-c iphone core-data