Ich muss NSManagedObject
Instanzen erstellen , einige Dinge mit ihnen machen und sie dann in den Papierkorb werfen oder in SQLite-Datenbank speichern. Das Problem ist, ich kann nicht Instanzen schafft NSManagedObject
nicht verbunden NSManagedObjectContext
und das bedeutet , ich habe irgendwie zu klären , nachdem ich entscheiden , dass ich einige der Objekte in meiner db nicht brauchen.
Um damit umzugehen, habe ich mit demselben Koordinator einen In-Memory-Speicher erstellt und platziere temporäre Objekte dort mit assignObject:toPersistentStore.
Now. Wie stelle ich sicher, dass diese temporären Objekte nicht an die Daten gelangen, die ich aus dem abrufe gemeinsam für beide Geschäfte Kontext? Oder muss ich für eine solche Aufgabe separate Kontexte erstellen?
UPD:
Jetzt denke ich darüber nach, einen separaten Kontext für den In-Memory-Speicher zu erstellen. Wie verschiebe ich Objekte von einem Kontext in einen anderen? Nur mit [context insertObject:]? Funktioniert es in diesem Setup einwandfrei? Wenn ich ein Objekt aus dem Objektdiagramm einfüge, wird das gesamte Diagramm auch in den Kontext eingefügt?
quelle
Antworten:
HINWEIS: Diese Antwort ist sehr alt. Siehe Kommentare für die vollständige Geschichte. Meine Empfehlung hat sich seitdem geändert und ich empfehle nicht mehr, nicht zugeordnete
NSManagedObject
Instanzen zu verwenden. Meine aktuelle Empfehlung ist die Verwendung temporärer untergeordneterNSManagedObjectContext
Instanzen.Ursprüngliche Antwort
Der einfachste Weg, dies zu tun, besteht darin, Ihre
NSManagedObject
Instanzen ohne zugehörige zu erstellenNSManagedObjectContext
.Dann, wenn Sie es speichern möchten:
quelle
iOS5 bietet eine einfachere Alternative zu Mike Wellers Antwort. Verwenden Sie stattdessen ein Kind NSManagedObjectContext. Das Trampolin durch das NSNotificationCenter entfällt
So erstellen Sie einen untergeordneten Kontext:
Erstellen Sie dann Ihre Objekte im untergeordneten Kontext:
Die Änderungen werden nur angewendet, wenn der untergeordnete Kontext gespeichert wird. Um die Änderungen zu verwerfen, speichern Sie sie einfach nicht.
Es gibt immer noch eine Einschränkung für Beziehungen. dh Sie können keine Beziehungen zu Objekten in anderen Kontexten erstellen. Um dies zu umgehen, verwenden Sie Objekt-IDs, um das Objekt aus dem untergeordneten Kontext abzurufen. z.B.
Beachten Sie, dass beim Speichern des untergeordneten Kontexts die Änderungen auf den übergeordneten Kontext angewendet werden. Durch Speichern des übergeordneten Kontexts bleiben die Änderungen erhalten.
Eine vollständige Erklärung finden Sie unter wwdc 2012, Sitzung 214 .
quelle
moc
im dritten Ausschnitt? Ist eschildContext
odermyMangedObjectContext
?NSManagedObject
bereits das Relevante bereitgestellt wirdNSManagedObjectContext
, können Sie die Auswahl des Kontexts automatisieren:NSManagedObject* objectRelatedContextually = [objectWithRelationship.managedObjectContext objectWithID:objectRelated.objectID];
und dannobjectWithRelationship.relationship = objectRelatedContextually;
.Der richtige Weg, um dies zu erreichen, ist ein neuer Kontext für verwaltete Objekte. Sie erstellen einen verwalteten Objektkontext mit demselben persistenten Speicher:
Dann fügen Sie neue Objekte hinzu, mutieren sie usw.
Wenn es Zeit zum Speichern ist, müssen Sie [tempContext save: ...] im tempContext aufrufen und die Speicherbenachrichtigung verarbeiten, um diese in Ihren ursprünglichen Kontext einzufügen. Um die Objekte zu verwerfen, geben Sie einfach diesen temporären Kontext frei und vergessen Sie ihn.
Wenn Sie also den temporären Kontext speichern, bleiben die Änderungen im Geschäft erhalten, und Sie müssen diese Änderungen nur wieder in Ihren Hauptkontext übernehmen:
Auf diese Weise sollten Sie auch Multithread-Kerndatenoperationen behandeln. Ein Kontext pro Thread.
Wenn Sie aus diesem temporären Kontext auf vorhandene Objekte zugreifen müssen (um Beziehungen usw. hinzuzufügen), müssen Sie die ID des Objekts verwenden, um eine neue Instanz wie die folgende zu erhalten:
Wenn Sie versuchen, eine
NSManagedObject
im falschen Kontext zu verwenden, werden beim Speichern Ausnahmen angezeigt.quelle
NSManagedObjectContext
sowohl im Speicher als auch in der CPU teuer ist. Mir ist klar, dass dies ursprünglich in einigen Apple-Beispielen der Fall war, aber diese Beispiele wurden aktualisiert und korrigiert.Das Erstellen temporärer Objekte aus dem Nullkontext funktioniert einwandfrei, bis Sie tatsächlich versuchen, eine Beziehung zu einem Objekt herzustellen, dessen Kontext! = Null!
Stellen Sie sicher, dass Sie damit einverstanden sind.
quelle
Was Sie beschreiben, ist genau das, wofür ein
NSManagedObjectContext
ist.Aus dem Core Data Programming Guide: Grundlagen der Core Data
Und Core Data Programming Guide: Validierung verwalteter Objekte
NSManagedObjectContext
s sind leicht ausgelegt. Sie können sie nach Belieben erstellen und verwerfen - es ist der Koordinator für beständige Geschäfte und die Abhängigkeiten, die "schwer" sind. Einem einzelnen persistenten Geschäftskoordinator können viele Kontexte zugeordnet sein. Unter dem älteren, veralteten Thread-Beschränkungsmodell würde dies bedeuten, dass für jeden Kontext derselbe persistente Speicherkoordinator festgelegt wird. Heute würde dies bedeuten, verschachtelte Kontexte mit einem Stammkontext zu verbinden, der dem persistenten Speicherkoordinator zugeordnet ist.Erstellen Sie einen Kontext, erstellen und ändern Sie verwaltete Objekte in diesem Kontext. Wenn Sie sie beibehalten und diese Änderungen mitteilen möchten, speichern Sie den Kontext. Andernfalls verwerfen Sie es.
Der Versuch, verwaltete Objekte unabhängig von einem zu erstellen,
NSManagedObjectContext
ist problematisch. Denken Sie daran, dass Core Data letztendlich ein Änderungsverfolgungsmechanismus für ein Objektdiagramm ist. Aus diesem Grund sind verwaltete Objekte wirklich Teil des Kontexts für verwaltete Objekte . Der Kontext beobachtet ihren Lebenszyklus , und ohne den Kontext funktionieren nicht alle Funktionen des verwalteten Objekts ordnungsgemäß.quelle
Abhängig von Ihrer Verwendung des temporären Objekts gibt es einige Einschränkungen bei den obigen Empfehlungen. Mein Anwendungsfall ist, dass ich ein temporäres Objekt erstellen und es an Ansichten binden möchte. Wenn der Benutzer dieses Objekt speichert, möchte ich Beziehungen zu vorhandenen Objekten einrichten und speichern. Ich möchte dies tun, um zu vermeiden, dass ein temporäres Objekt erstellt wird, das diese Werte enthält. (Ja, ich könnte einfach warten, bis der Benutzer speichert, und dann den Ansichtsinhalt abrufen, aber ich füge diese Ansichten in eine Tabelle ein, und die Logik dafür ist weniger elegant.)
Die Optionen für temporäre Objekte sind:
1) (Bevorzugt) Erstellen Sie das temporäre Objekt in einem untergeordneten Kontext. Dies funktioniert nicht, da ich das Objekt an die Benutzeroberfläche binde und nicht garantieren kann, dass die Objekt-Accessoren im untergeordneten Kontext aufgerufen werden. (Ich habe keine Dokumentation gefunden, in der etwas anderes angegeben ist, daher muss ich davon ausgehen.)
2) Erstellen Sie das temporäre Objekt mit dem Objektkontext Null. Dies funktioniert nicht und führt zu Datenverlust / -beschädigung.
Meine Lösung: Ich habe dieses Problem gelöst, indem ich das temporäre Objekt mit dem Objektkontext Null erstellt habe. Wenn ich das Objekt jedoch speichere, anstatt es als Nummer 2 einzufügen, kopiere ich alle seine Attribute in ein neues Objekt, das ich im Hauptkontext erstelle. Ich habe in meiner NSManagedObject-Unterklasse eine unterstützende Methode namens cloneInto erstellt, mit der ich Attribute und Beziehungen für jedes Objekt einfach kopieren kann.
quelle
Für mich hat Marcus 'Antwort nicht funktioniert. Folgendes hat bei mir funktioniert:
dann, wenn ich mich entscheide, es zu speichern:
Wir dürfen auch nicht vergessen, es freizugeben
quelle
Ich schreibe diese Antwort für Swift neu, da alle ähnlichen Fragen schnell auf diese Frage umgeleitet werden.
Mit dem folgenden Code können Sie das Objekt ohne ManagedContext deklarieren.
Um das Objekt später zu speichern, können Sie es in den Kontext einfügen und speichern.
quelle