У моей старой модели данных ядра есть поле NSDate
, которое я хотел бы изменить на NSNumber
. Я прочитал документацию Apple, и несколько подобных вопросов на SO и другие блоги (см ссылки в конце вопроса)Первичная миграция основных данных
Но независимо от того, что я делаю, я получаю ту же ошибку:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Mismatch between mapping and source/destination models'
У меня есть только 2 версии модели, и я снова и снова проверял правильность исходной и целевой моделей.
Я даже отбросил все свои изменения и воссоздал новую модель, сопоставления и объекты (NSManagedObject
подклассы). Я застрял на этом уже почти 2 дня и больше не знаю, что я делаю. Любые указатели на то, что я делаю неправильно, будут очень благодарны.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Old.sqlite"];
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSString *sourceStoreType = NSSQLiteStoreType;
NSURL *sourceStoreURL = storeURL;
NSURL *destinationStoreURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"New.sqlite"];
NSString *destinationStoreType = NSSQLiteStoreType;
NSDictionary *destinationStoreOptions = nil;
NSDictionary *sourceMetadata =
[NSPersistentStoreCoordinator metadataForPersistentStoreOfType:sourceStoreType
URL:sourceStoreURL
error:&error];
if (sourceMetadata == nil) {
NSLog(@"source metadata is nil");
}
NSManagedObjectModel *destinationModel = [_persistentStoreCoordinator managedObjectModel];
BOOL pscCompatibile = [destinationModel
isConfiguration:nil
compatibleWithStoreMetadata:sourceMetadata];
if (pscCompatibile) {
// no need to migrate
NSLog(@"is compatible");
} else {
NSLog(@"is not compatible");
NSManagedObjectModel *sourceModel =
[NSManagedObjectModel mergedModelFromBundles:nil
forStoreMetadata:sourceMetadata];
if (sourceModel != nil) {
NSLog(@"source model is not nil");
NSMigrationManager *migrationManager =
[[NSMigrationManager alloc] initWithSourceModel:sourceModel
destinationModel:destinationModel];
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"MyMigrationMapping" withExtension:@"cdm"];
NSMappingModel *mappingModel = [[NSMappingModel alloc] initWithContentsOfURL:fileURL];
NSArray *newEntityMappings = [NSArray arrayWithArray:mappingModel.entityMappings];
for (NSEntityMapping *entityMapping in newEntityMappings) {
entityMapping.entityMigrationPolicyClassName = NSStringFromClass([ConvertDateToNumberTransformationPolicy class]);
}
mappingModel.entityMappings = newEntityMappings;
BOOL ok = [migrationManager migrateStoreFromURL:sourceStoreURL
type:sourceStoreType
options:nil
withMappingModel:mappingModel
toDestinationURL:destinationStoreURL
destinationType:destinationStoreType
destinationOptions:nil
error:&error];
if (ok) {
storeURL = destinationStoreURL;
}
} else {
NSLog(@"e nil source model");
}
}
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
nil];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return _persistentStoreCoordinator;
}
Мой заказ NSEntityMigration
класс:
- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance
entityMapping:(NSEntityMapping *)mapping
manager:(NSMigrationManager *)manager
error:(NSError **)error
{
// Create a new object for the model context
NSManagedObject *newObject =
[NSEntityDescription insertNewObjectForEntityForName:[mapping destinationEntityName]
inManagedObjectContext:[manager destinationContext]];
NSArray *arrayOfKeys = @[@"startDate", @"endDate", @"creationTime", @"timeStamp"];
for (NSString *key in arrayOfKeys) {
// do our transfer of NSDate to NSNumber
NSDate *date = [sInstance valueForKey:key];
NSLog(@"Key: %@, value: %@", key, [date description]);
// set the value for our new object
[newObject setValue:[NSNumber numberWithDouble:[date timeIntervalSince1970]] forKey:key];
}
// do the coupling of old and new
[manager associateSourceInstance:sInstance withDestinationInstance:newObject forEntityMapping:mapping];
return YES;
}
Некоторые ссылки:
- Example or explanation of Core Data Migration with multiple passes?
- Core Data - Default Migration (Manual)
- http://www.preenandprune.com/cocoamondo/?p=468
- http://www.timisted.net/blog/archive/core-data-migration/
@Nishant Попробуйте настроить com.apple.CoreData.MigrationDebug предпочтение 1? – Willeke
@ Виллеке Да, я сделал это. Это явно не говорит мне, почему это несоответствие между сопоставлениями происходит. – Nishant
Очень сложно сказать, почему вы получаете ошибку. Задайте новый вопрос и скажите, что вы изменили на модель данных, что вы изменили на модель сопоставления по умолчанию, что вы сделали в коде и что такое аналогичная проблема. – Willeke