2012-11-21 3 views
6

Ich habe zwei Modellvarianten - 12 und 13. Dann habe ich eine xcmappingmodel-Datei mit Quelle 12 und Ziel 13Core Data Migration: Methoden in NSEntityMigrationPolicy nicht aufgerufen.

I subclassed NSEntityMigrationPolicy und fügte hinzu, meine Klasse der mappingmodel-Datei an die gewünschte Einheit.

@interface EndDateMigrationPolicy : NSEntityMigrationPolicy 

enter image description here

Nach der Installation und ältere Version (11) auf dem Gerät, installiere ich den aktuellen Status mit Modellversion 13 - die App läuft, sind aber meine Migrationsmethoden nicht genannt. Fehle ich etwas?

EDIT: Ist es richtig, diese Optionen zu verwenden?

NSDictionary *options = @{NSMigratePersistentStoresAutomaticallyOption: @YES, 
         NSInferMappingModelAutomaticallyOption: @YES}; 
+0

Ich habe ein ähnliches Problem. Hast du dieses Problem gelöst? Wenn ja, bitte posten Sie die Antwort. –

Antwort

3

Ich werde versuchen Sie, so gut zu beantworten, ich kann, ich habe so Migrationen Daten Kern schon ein paar Mal durchlitt ich weiß, wie schmerzhaft es ist. Zum einen können Sie nicht hoffen, dass Ihre Migration mit diesen Optionen arbeiten muss, denn das, was Sie zu tun versuchen, ist eigentlich keine leichte Migration und dennoch sagen Sie, dass Sie eine einfache Migration durchführen müssen.

Grundsätzlich sagen wir, Sie aus irgendeinem Grund brauchen eine nicht leichte Migration zwischen zwei Versionen zu haben, in Ihrem Fall 11 und 12. Was Sie tun müssen, ist zu tun:

1-> 12 leichte 12- > 13 benutzerdefinierte Migration 13 -> (zukünftige Version) leichte Migration

Es könnte eine bessere Lösung sein, aber ich habe es noch nicht gefunden.

Hier ist ein Code, um Ihnen zu helfen (die schwierigsten Teile, ich kann nicht alles auswendig erinnern), vor diesem Code kopiere ich die Datenbank auf ein Backup, also im Grunde die Backup-Datenbank ist Ihre alte und der Laden ist Ihre neue (die leer ist)

NSString *path = [[NSBundle mainBundle] pathForResource:<YOUR MODEL NAME> ofType:@"cdm"]; 

NSURL *backUpURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"<YOUR MODEL NAME>MigrationBackUp.sqlite"]; //or whatever you want to call your backup 
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"<YOUR MODEL NAME>.sqlite"]; 
NSError *err2 = nil; 
NSDictionary *sourceMetadata2 = 
[NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType 
                  URL:backUpURL 
                 error:&err2]; 
NSManagedObjectModel *sourceModel2 = [NSManagedObjectModel mergedModelFromBundles:[NSArray arrayWithObject:[NSBundle mainBundle]] 

                   forStoreMetadata:sourceMetadata2]; 
NSManagedObjectModel *destinationModel2 = [self managedObjectModelForVersion:@"1.4"]; //Yeah your gonna have to get your mapping model , I'll give you this code too later 
NSString *oldModel = [[sourceModel2 versionIdentifiers] anyObject]; 
NSLog(@"Source Model : %@",oldModel); 
NSMappingModel *mappingModel = [[NSMappingModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path]]; 

if (mappingModel != nil) { 
    for (NSString * identifier in [mappingModel entityMappings]) { 
     NSLog(@"Mapping > %@",identifier); 
    } 
} 

Dann machen Sie einfach einen Migrator mit Ihrer Quelle und Ziel. Diese

ist auch ein schwieriger Teil danach:

BOOL success = [migrator migrateStoreFromURL:backUpURL 
             type:NSSQLiteStoreType 
            options:nil 
          withMappingModel:mappingModel 
          toDestinationURL:storeURL 
          destinationType:NSSQLiteStoreType 
          destinationOptions:nil 
             error:&err2]; 

Last but not least (ich sagte ich Sie, bevor geben würde):

- (NSManagedObjectModel *)managedObjectModelForVersion:(NSString*)version { 

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"Model" ofType:@"momd"]; 
if (BETWEEN_INEX(version, @"1.0", @"1.4")) { 
    modelPath = [modelPath stringByAppendingPathComponent:@"Model"]; 
    modelPath = [modelPath stringByAppendingPathExtension:@"mom"]; 
} else if (BETWEEN_INEX(version, @"1.4", @"1.5")) { 
    modelPath = [modelPath stringByAppendingPathComponent:@"Model 2"]; 
    modelPath = [modelPath stringByAppendingPathExtension:@"mom"]; 
} else if (BETWEEN_INEX(version, @"1.5", @"1.6")) { 
    modelPath = [modelPath stringByAppendingPathComponent:@"Model 3"]; 
    modelPath = [modelPath stringByAppendingPathExtension:@"mom"]; 
} else if (BETWEEN_INEX(version, @"1.6", @"1.7")) { 
    modelPath = [modelPath stringByAppendingPathComponent:@"Model 4"]; 
    modelPath = [modelPath stringByAppendingPathExtension:@"mom"]; 
} 
NSURL *modelURL = [NSURL fileURLWithPath:modelPath]; 
NSManagedObjectModel * oldManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 
NSSet *vIdentifiers = [oldManagedObjectModel versionIdentifiers]; 
for (NSString * identifier in vIdentifiers) { 
    NSLog(@"Old Model : %@",identifier); 
} 
return [oldManagedObjectModel autorelease]; 

}

Ich weiß, Dies sind nur Codeschnipsel, aber ich hoffe wirklich, dass es Ihnen hilft, Ihr Problem zu lösen. Wenn Sie etwas anderes brauchen, fragen Sie einfach.

+0

ist das wirklich der beste Weg? Ist es nicht einfacher, leichte und komplexe Migrationen zu "mischen"? – swalkner

+0

Ich bin mir ziemlich sicher, dass es der einfachste Weg ist. Ein Migrationsmodell kann nur zwei Schemaversionen referenzieren. Der komplizierte Teil vermischt nicht wirklich die Migrationen, das ist irgendwie einfach, du machst sie nur seriell, die komplexe Migration ist, wo die Schwierigkeit wirklich liegt. – thewormsterror

1

Ihre NSEntityMigrationPolicy wird nicht aufgerufen, weil Sie NSInferMappingModelAutomaticallyOption zu @ (JA) gesetzt - sollte es sein @ (NO)