4 Stimmen

Hinzufügen einer Instanz von NSManagedObject zu NSManagedObjectContext ok, Aktualisieren derselben Instanz fehlgeschlagen

Ich verwende Kerndaten in meiner iPhone-App. Ich habe eine einfache Klasse erstellt Freund die sich ableitet von NSManagedObject und der die folgende Eigenschaft verwendet:

@property (nonatomic, retain) NSString *name;

Ich bin in der Lage, Instanzen dieser Klasse zu meinem Kontext hinzuzufügen und zu löschen, und meine Änderungen sind auch persistent.
Jetzt möchte ich Aktualisieren/Ändern a Freund -Instanz und machen sie wieder persistent.

Aber das scheint nicht zu funktionieren.

Hier ist ein Teil des Codes, der mein Problem zeigt:

//  NSManagedObjectContext *context  = < my managed context> 
//   NSFetchedResultsController *nsfrc= < my fetched result controller>

NSEntityDescription *entity = [nsfrc entity];
NSManagedObject *newManagedObject = [NSEntityDescription 
       insertNewObjectForEntityForName:[entity name]  inManagedObjectContext:context];

Friend *f = (Friend *) newManagedObject;
f.name = @"name1";
//1.  --- here context.hasChanges == 1 ---   ok

NSError *error = nil;
if (![context save:&error]) { ... }
//2.  --- here context.hasChanges == 0 ---   ok

f.name = @"name2";
//3.  --- here context.hasChanges == 0 ---   nok?

if (![context save:&error]) { ... }

Bei Kommentar 1 ist alles in Ordnung. Ich habe eine neue NSManagedObject der Freund -Typ und ich kann die Eigenschaft name ändern. Der Kontext zeigt mir, dass es etwas zu speichern gibt. Nach dem Speichern des Kontexts sehe ich context.hasChanges == 0 . Beachten Sie auch, dass die Daten nach dem Speichern des Kontexts erhalten bleiben.

Nach Kommentar 2 ändere ich die Eigenschaft name. Jetzt würde ich erwarten context.hasChanges == 1 und auch nach der Kontext speichern Ich würde erwarten, dass der neue Name beständig ist. Aber leider ist er das nicht. Wenn ich die Anwendung erneut starte, wird die Freund Instanz mit der name-Eigenschaft = @"name1" .

Ich kann in der Kerndatendokumentation keine Hinweise oder Beispiele finden. Was mache ich also falsch? Was muss ich tun, um eine bestehende Datei zu aktualisieren/ändern? Freund -Instanz zu ändern und sie dauerhaft zu machen?

Die einzige Lösung, die ich sehe, ist, den Eintrag zu löschen, ihn zu ändern und erneut hinzuzufügen. Aber ich glaube nicht, dass dies der richtige Weg ist.

Danke!

5voto

Martin Lockett Punkte 1800

Dass die Änderungen nicht erkannt wurden, lag möglicherweise daran, dass Sie in Ihrer Unterklassenimplementierung @synthesize anstelle von @dynamic verwendet haben. CD stellt seine eigenen Accessoren zur Verfügung, die Sie mit @synthesize umgehen werden. Martin

1voto

TechZen Punkte 64117

Das einzige, was ich mir vorstellen kann, ist, dass der Kontext Probleme hat, das Friend-Objekt zu beobachten, weil Sie es als generisches NSManagedObject anstelle einer Instanz der Friend-Unterklasse initialisiert haben.

Das generische NSManagedObject speichert keine Werte in Eigenschaften, wie es seine Unterklassen tun. Stattdessen wird ein assoziativer Speicher verwendet, der mit einem generischen Wörterbuch vergleichbar ist. Mit anderen Worten, ein generisches NSManagedObject speichert und greift auf Werte an einem anderen Ort und mit einer anderen Methode des Setzens und Holens zu als seine Unterklasse. Zur Laufzeit kann dies zu Verwirrung im Kontext führen.

Beim ersten Mal, wenn Sie den Kontext prüfen, erhalten Sie eine hasChangess==YES weil Sie ein neues Objekt in den Objektgraphen eingefügt haben. Beim zweiten Mal ändern Sie lediglich ein Attribut eines bestehenden Objekts. Wenn der Kontext den Wert des Attributs nicht genau beobachten kann name Taste weiß er nicht, dass er das Objekt beim zweiten Durchgang erneut speichern muss.

Ändern:

NSManagedObject *newManagedObject = [NSEntityDescription 
       insertNewObjectForEntityForName:[entity name]  inManagedObjectContext:context];

...zu:

Friend *newFriend = [NSEntityDescription 
       insertNewObjectForEntityForName:[entity name]  inManagedObjectContext:context];

... und sehen Sie, ob das Problem dadurch gelöst wird.

Ansonsten sieht der Code gut aus.

1voto

Zensursula Punkte 173

Endlich die Lösung gefunden! Für meine obige Frage habe ich allen unnötigen Code entfernt (leider auch mein Problem). Also, um diesen Thread zu vervollständigen:
Meine Friend -Klasse hat auch ein Mitglied:

@property (nonatomic) int duration;

In meiner Testumgebung habe ich auch die duration (immer wenn ich die name ). Dies scheint der Grund dafür zu sein, dass der Kontext keine Veränderung erkennen kann. Wenn ich die Eigenschaft in

@property (nonatomic, retain) NSNumber duration;

hat alles gut funktioniert. Beachten Sie, dass mein xdatamodel eine Eigenschaft hat duration vom Typ Int32 . Was ich nicht verstehe, ist, warum beim ersten Mal alles funktioniert hat. [context save]; . Aber das ist für mich im Moment in Ordnung.

Um hier einige gute Ratschläge zu geben:

Generieren Sie Ihr xdatemodel NICHT aus Ihrer von NSManagedObject abgeleiteten Klasse (wie ich es getan habe). Erstellen Sie stattdessen Ihr xdatemodel und generieren Sie dann Ihre Klasse aus Ihrem Modell (Xcode->Design->DataModel->Copy Obj-C2.0..)!
( Aktualisierung 03/2011: Die Generierung der Klassen aus dem Modell funktioniert in XCode 4.0 wie ein Zauberspruch)

Ich wünschte, ich hätte das schon früh an diesem schönen Sonntagmorgen gewusst.
Guten Abend!

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X