【发布时间】:2013-04-19 18:54:44
【问题描述】:
我的旧核心数据模型有一个NSDate 字段,我想将其更改为NSNumber。我在 SO 和其他博客上阅读了 Apple 文档和几个类似的问题(请参阅问题末尾的参考资料)
但无论我做什么,我都会收到同样的错误:
由于未捕获的异常“NSInvalidArgumentException”而终止应用,原因:“映射与源/目标模型不匹配”
我只有两个版本的模型,而且我已经反复验证源模型和目标模型是正确的。
我什至放弃了所有更改并重新创建了一个新模型、映射和实体(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;
}
一些参考资料:
【问题讨论】:
-
@Nishant 您是否尝试将 com.apple.CoreData.MigrationDebug 首选项设置为 1?
-
@Willeke 是的,我做到了。这并没有明确告诉我为什么会发生映射之间的这种不匹配。
-
很难从这里判断为什么会出现错误。提出一个新问题,并说明您对数据模型进行了哪些更改,对默认映射模型进行了哪些更改,您在代码中做了什么以及类似的问题是什么。
-
@Nishant。我注意到在您的“createDestinationInstanceFromSourceInstance”方法中,您创建了一个类型为 n 的新托管对象,其中 n 可能是实体映射对象给定的任何类型。然后,您假设该实体类型的 newObject 具有属性“startDate”、“endDate”、“creationTime”、“timeStamp”。可能是映射仅包含一个目标实体类型,所以这可能不是您的问题(或者您的模型中的每个实体类型都可能具有这些属性),但是如果我尝试设置这些属性,我会在尝试设置这些属性之前进行一些实体类型检查你是吗?
-
@TheBasicMind 如果我根本不实现“createDestinationInstancesForSourceInstance”怎么办。我只想要多个映射来迁移我拥有的大数据。不需要自定义迁移。什么是正确的方法?
标签: ios objective-c core-data core-data-migration