Was muss ich tun, damit Core Data Modelle automatisch migriert?

96

Ich habe die Dokumentation zur automatischen / Lightweight-Migration für Core Data-Modelle gelesen, habe jedoch Probleme bei der Implementierung.

Soweit ich weiß, sollte die Anwendung feststellen, dass das Modell und das Modell, das bereits auf einem Gerät vorhanden ist, nicht identisch sind. Wenn Sie nur Attribute oder Beziehungen und ähnliche einfache Änderungen hinzugefügt haben, sollte das Modell automatisch aktualisiert werden.

Irgendwelche Hinweise - muss ich etwas in Xcode setzen?

Grouchal
quelle

Antworten:

138

Ich habe jetzt herausgefunden, dass dies ganz einfach ist - sobald Sie wissen, wo Sie suchen müssen.

In meinem AppDelegate habe ich den NSPersistentStoreCoordinator eingerichtet - und Sie müssen einige Optionen hinzufügen, damit er die automatische Migration übernimmt:

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:

[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,

[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

NSError *error;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];

if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
    // Handle error
    NSLog(@"Problem with PersistentStoreCoordinator: %@",error);
}

Dann müssen Sie einen kleinen Trick in xCode machen:

  1. Wählen Sie Ihre xcdatamodel-Datei aus
  2. Wählen Sie oben das Design-Menü - dann Datenmodell - und dann Modellversion hinzufügen
  3. Ihre xcdatamodel-Datei wird dann in ein neues Verzeichnis mit demselben Namen wie Ihre xcdatamodel-Datei verschoben, jedoch mit der Erweiterung xcdatamodeld. In diesem Verzeichnis befindet sich eine zweite Datei mit einer 2 im Namen. Wählen Sie die neue Datei und dann Design-> Datenmodell-> Aktuelle Version festlegen ( in Xcode 4 tun Sie dies )
  4. Wenn Sie bereits die Änderungen vorgenommen haben, die dazu geführt haben, dass Ihr Projekt nicht kompatibel ist, nehmen Sie diese Änderungen aus der ursprünglichen xcdatamodel-Datei. Wenn Sie die Änderungen noch nicht vorgenommen haben, bearbeiten Sie einfach die Datei 2.xcdatamodel (die Sie gerade in der aktuellen Version erstellt haben).
  5. Wenn Sie diese Version auf einem Gerät mit dem alten Modell installieren, wird dieses Modell automatisch auf das neue Modell aktualisiert.

Dies scheint großartig und so einfach zu sein, wie ich es wollte - aber ich denke, Sie müssen bei der Entwicklung vorsichtig sein, wenn Sie ein Modell ändern - andernfalls müssen Sie für jede Änderung eine neue Version erstellen.

Ich denke, ich werde alle geänderten Dateien behalten und dann, sobald ich bereit bin, mein Update bereitzustellen, alle dazwischen liegenden Dateien löschen und nur mit den ältesten und neuesten Modellen bereitstellen.


UPDATE (15.07.2011):

Vielen Dank an @ rockstarberlin für den Hinweis, dass es bei Apple eine aktualisierte Dokumentation gibt:

Xcode 4: Festlegen der aktuellen Version eines verwalteten Objektmodells

Update: 19.08.2013 besserer Link:

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/vmModelFormat.html

Grouchal
quelle
Ich würde vorschlagen, das Handbuch zur Migration und Versionierung von Kerndaten zu lesen, das im Xcode Doc Viewer und auf developer.apple.com verfügbar ist.
Hunter
1
Ich fand die Antwort dort nicht einfach - es dauerte eine Weile, bis ich herausfand, wie das geht.
Grouchal
NSInferMappingModelAutomaticallyOption funktioniert gut, jedoch nur für einfache Zuordnungen wie das Ändern des Namens eines Attributs. Für kompliziertere Aufgaben (Beziehungen, Entfernen oder Hinzufügen von Entitäten) müssen Sie ein Zuordnungsmodell hinzufügen. Wenn Xcode sich darüber beschwert, dass NSInferMappingModelAutomaticallyOption nicht deklariert ist, fügen Sie #import <CoreData / CoreData.h> zu Ihrer App-Delegat-Headerdatei hinzu.
Elise van Looij
Ich habe meinem Modell einige Entitäten hinzugefügt und den berüchtigten Fehler "Das zum Öffnen des Geschäfts verwendete Modell ist nicht mit dem zum Erstellen des Geschäfts verwendeten Modell kompatibel" erhalten. Ihre Lösung hat es behoben! Vielen Dank!
Karsten Silz
1
Lesen Sie die Antwort von Santthosh weiter unten, wenn nach Befolgen dieser Anweisungen der Fehler "Modelle können nicht mit zwei verschiedenen Entitäten mit dem Namen zusammengeführt werden" angezeigt wird.
BenvolioT
14

Das war unglaublich hilfreich. Die Apple-Dokumentation war - wie immer - absolut unvollständig. Ich empfehle einen sauberen Build, da beim ersten Ausführen nach diesen Änderungen der Fehler "Modelle können nicht mit zwei verschiedenen Entitäten xxx zusammengeführt werden" aufgetreten ist. Der saubere Build hat es behoben.

Scott bedeutet
quelle
Ein sauberer Build hat auch meine Probleme behoben.
Jrainbow
6

Die Antwort von Grouchal ist perfekt ... aber wenn Sie immer noch die Option "Modelle können nicht mit zwei verschiedenen Entitäten zusammengeführt werden xxx" haben, auch nachdem Sie den Build mehrmals bereinigt haben ... Möglicherweise haben Sie Probleme mit dem Laden des verwalteten Objektmodells. Schauen Sie sich dieses an ... was mir geholfen hat, es zu reparieren.

Kernprobleme bei der Datenmigration

Santthosh
quelle
3

Wenn Sie wie ich auf diesen Beitrag gestoßen sind, nachdem Sie den Fehler "Das zum Öffnen des Geschäfts verwendete Modell ist nicht mit dem zum Erstellen des Geschäfts verwendeten Modell kompatibel" erhalten haben, debuggen Sie nur mit dem Simulator und möchten das Problem vollständig ersetzen Wenn das alte Modell installiert ist, können Sie einfach die Simulator-App zurücksetzen oder das Löschen Ihrer App aus dem Simulator würde wahrscheinlich auch funktionieren.

Es kam mir erst in den Sinn, dies zu versuchen, als ich die Beiträge hier gelesen hatte. Zu diesem Zeitpunkt wurde mir klar, dass ich die App im Simulator installiert und anschließend das Modell geändert hatte, was den oben genannten Laufzeitfehler verursachte.

dreyln
quelle
1

Um Santthoshs Antwort zu verfolgen, dachte ich, ich würde stattdessen das Code-Snippet hier posten. Sie benötigen managedObjectModel mit erstellen , initWithContentsOfURL:anstatt mergedModelFromBundles:sonst bringen Sie Fehler:

Modelle können nicht mit zwei verschiedenen Entitäten XXX und XXX zusammengeführt werden

Wenn Ihre Modelldatei den Namen "Modell" trägt, erstellen Sie das verwaltete Objektmodell folgendermaßen:

NSString *path = [[NSBundle mainBundle] pathForResource:@"Model" ofType:@"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL]; 

Dank an diesen Blog-Beitrag .

Samvermette
quelle
1

Ich habe dieses Problem seit Jahren und habe alle diese Antworten ohne Erfolg ausprobiert. Heute habe ich endlich herausgefunden, was ich falsch gemacht habe. Sehr einfaches Problem, aber ich habe es übersehen. Wenn Sie beim Erstellen einer neueren Version des Datenmodells Spalten hinzufügen, müssen Sie diese als OPTIONAL markieren. Wenn Sie dies nicht tun, funktioniert die einfache Migration nicht, da die neuen Spaltenwerte nicht ausgefüllt werden.

Sobald ich sichergestellt habe, dass in meinen neuen Spalten "optional" aktiviert ist, habe ich die Migration erneut versucht und es hat funktioniert.

Brain2000
quelle
1

Ich bin auf diesen Beitrag aufgrund eines anderen Problems gestoßen, aber der Fehler war " Die zum Öffnen des Geschäfts verwendete Modellkonfiguration ist nicht mit der zum Erstellen des Geschäfts verwendeten kompatibel." "

Hier war mein Problem und die Lösung dafür. In meinem Modell habe ich Konfigurationen verwendet . Ich hatte einige der Entitäten in einer Datei und die anderen in einer zweiten Datei gespeichert. (Ich habe einige Standardeinstellungen, die möglicherweise regelmäßig heruntergeladen werden müssen, und es wäre ein unglaublicher Schmerz, sie zu einem Ganzen zusammenzuführen). Jedenfalls habe ich eine neue Einheit geschaffen. Das Programm schien gut zu laufen, aber wann immer ich aufhörte, bekam ich den obigen Fehler.

Die Lösung bestand darin, meine Konfigurationen zu überprüfen, festzustellen, dass ich eine Entität hatte, die sich derzeit in keiner der Konfigurationen befand, und sie einer hinzuzufügen. Läuft wie ein Traum.

Dies wird das Problem des OP nicht beheben. Aber vielleicht ist eine frustrierte Person, die hier über Google landet, in dem Boot, in dem ich war :)

Der Cappy
quelle
0

iOS 4.0+

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"model" withExtension:@"momd"];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
Stian Høiland
quelle
0

Kleinere Änderungen an @ Grouchals fantastischen Anweisungen oben für Xcode Version 5:

Alt: 2. Wählen Sie oben das Design-Menü - dann Datenmodell - und dann Modellversion hinzufügen

Version 5+: 2. Wählen Sie das Menü Editor und dann Modellversion hinzufügen…, geben Sie Ihren Versionsnamen ein und wählen Sie Modellbasiert aus (wählen Sie Ihr Originalmodell aus der Liste aus).

PGSeattle
quelle