Mô hình dữ liệu cốt lõi cũ của tôi có trường NSDate
, mà tôi muốn thay đổi thành NSNumber
. Tôi đọc tài liệu của Apple và một số câu hỏi tương tự trên SO và các blog khác (xem tài liệu tham khảo ở cuối của câu hỏi)Di chuyển tùy chỉnh dữ liệu chính
Nhưng không có vấn đề gì tôi làm, tôi tiếp tục nhận được lỗi tương tự:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Mismatch between mapping and source/destination models'
tôi chỉ có 2 phiên bản của mô hình, và tôi đã xác minh thời gian và một lần nữa rằng các mô hình nguồn và đích là chính xác.
Tôi thậm chí đã bỏ tất cả các thay đổi của mình và tạo lại một mô hình, ánh xạ và thực thể mới (NSManagedObject
các lớp con). Tôi đã bị mắc kẹt này trong gần 2 ngày nay, và không còn manh mối nào nữa về những gì tôi đang làm. Bất kỳ gợi ý về những gì tôi đang làm sai sẽ được đánh giá cao.
- (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;
}
tùy chỉnh của tôi NSEntityMigration
lớp:
- (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;
}
Một số tài liệu tham khảo:
- 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 Bạn đã thử đặt tùy chọn com.apple.CoreData.MigrationDebug thành 1? – Willeke
@Willeke Vâng, tôi đã làm điều đó. Điều đó không rõ ràng cho tôi biết tại sao sự không khớp này giữa các ánh xạ đang xảy ra. – Nishant
Rất khó để kể từ đây tại sao bạn gặp lỗi. Đặt một câu hỏi mới và cho biết những gì bạn đã thay đổi thành mô hình dữ liệu, những gì bạn đã thay đổi thành mô hình ánh xạ mặc định, những gì bạn đã làm trong mã và vấn đề tương tự là gì. – Willeke