Фон
Предыдущая версия атрибута приложения установлена как 16-битная в Базовых данных.Это было слишком мало, чтобы содержать большие значения, превышающие приблизительно 32768.
int 16 использует 1 бит для представления знака, поэтому максимальное значение = 2 ^ 15 = 32768
В iOS 5 эти значения переполнились отрицательными числами.
34318 стал -31218
36745 стал -28791
Чтобы исправить эти отрицательные значения, добавьте 2 ^ 16 = 65536
Обратите внимание, что это решение работает, только если исходное значение было меньше 65536.
Добавление новой модели
В файловом навигаторе выберите MyApp.xcdatamodeld
Выберите меню Редактор / Добавить версию модели
Имя версии: предлагается «MyApp 2», но выможно изменить, например, на MyAppVersion2
В зависимости от модели: MyApp
В новом MyAppVersion2.xcdatamodel изменить тип атрибута с целого числа 16 на целое число 64.
В файловом навигаторе выбрать каталог MyApp.xcdatamodeld
Инспектор открытой правой панели, Версионная модель данных ядра Текущее изменение с MyApp на MyAppVersion2.В навигаторе файлов левой панели зеленая галочка перемещается из MyApp.xcdatamodel в MyAppVersion2.xcdatamodel.
В MyAppAppDelegate managedObjectModel не меняйте имя ресурса из @ "MyApp"
В Xcode выберите папку ModelClasses.
Файл / Добавить базовую модель отображения данных.
Выбор исходной модели данных MyApp.xcdatamodel
Выбор целевой модели данных MyAppVersion2.xcdatamodel
Сохранить как MyAppToMyAppVersion2.xcmappingmodel
Добавить к цели MyApp.
В MyAppAppDelegate persistentStoreCoordinator включить ручную миграцию CoreData
// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created
// and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator_ != nil) {
return persistentStoreCoordinator_;
}
NSURL *storeURL = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory]
stringByAppendingPathComponent: @"MyApp.sqlite"]];
NSError *error = nil;
persistentStoreCoordinator_ = [[NSPersistentStoreCoordinator alloc]
initWithManagedObjectModel:[self managedObjectModel]];
// Set Core Data migration options
// For automatic lightweight migration set NSInferMappingModelAutomaticallyOption to YES
// For manual migration using a mapping model set NSInferMappingModelAutomaticallyOption to NO
NSDictionary *optionsDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],
NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:NO],
NSInferMappingModelAutomaticallyOption,
nil];
if (![persistentStoreCoordinator_ addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:optionsDictionary
error:&error])
{
// handle the error
NSString *message = [[NSString alloc]
initWithFormat:@"%@, %@", error, [error userInfo]];
UIAlertViewAutoDismiss *alertView = [[UIAlertViewAutoDismiss alloc]
initWithTitle:NSLocalizedString(@"Sorry, Persistent Store Error. Please Quit.", @"")
message:message
delegate: nil
cancelButtonTitle:NSLocalizedString(@"OK", @"")
otherButtonTitles:nil];
[message release];
[alertView show];
[alertView release];
}
return persistentStoreCoordinator_;
}
Добавить политику миграции
MyAppToMyAppVersion2MigrationPolicy
В следующем примере выполняется преобразование одной сущности «Среда» с целочисленным атрибутом «FeedID» и строковым атрибутом «заголовок».
- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)aSource
entityMapping:(NSEntityMapping *)mapping
manager:(NSMigrationManager *)migrationManager
error:(NSError **)error {
NSEntityDescription *aSourceEntityDescription = [aSource entity];
NSString *aSourceName = [aSourceEntityDescription valueForKey:@"name"];
NSManagedObjectContext *destinationMOC = [migrationManager destinationContext];
NSManagedObject *destEnvironment;
NSString *destEntityName = [mapping destinationEntityName];
if ([aSourceName isEqualToString:kEnvironment])
{
destEnvironment = [NSEntityDescription
insertNewObjectForEntityForName:destEntityName
inManagedObjectContext:destinationMOC];
// attribute feedID
NSNumber *sourceFeedID = [aSource valueForKey:kFeedID];
if (!sourceFeedID)
{
// Defensive programming.
// In the source model version, feedID was required to have a value
// so excecution should never get here.
[destEnvironment setValue:[NSNumber numberWithInteger:0] forKey:kFeedID];
}
else
{
NSInteger sourceFeedIDInteger = [sourceFeedID intValue];
if (sourceFeedIDInteger < 0)
{
// To correct previous negative feedIDs, add 2^16 = 65536
NSInteger kInt16RolloverOffset = 65536;
NSInteger destFeedIDInteger = (sourceFeedIDInteger + kInt16RolloverOffset);
NSNumber *destFeedID = [NSNumber numberWithInteger:destFeedIDInteger];
[destEnvironment setValue:destFeedID forKey:kFeedID];
} else
{
// attribute feedID previous value is not negative so use it as is
[destEnvironment setValue:sourceFeedID forKey:kFeedID];
}
}
// attribute title (don't change this attribute)
NSString *sourceTitle = [aSource valueForKey:kTitle];
if (!sourceTitle)
{
// no previous value, set blank
[destEnvironment setValue:@"" forKey:kTitle];
} else
{
[destEnvironment setValue:sourceTitle forKey:kTitle];
}
[migrationManager associateSourceInstance:aSource
withDestinationInstance:destEnvironment
forEntityMapping:mapping];
return YES;
} else
{
// don't remap any other entities
return NO;
}
}
В файловом навигаторе выберите MyAppToMyAppVersion2.xcmappingmodel
В окне, показать правую панель утилит.
В окне выберите Entity Mappings Environ.mentToEnvironment
В правой части Entity Mapping выберите Custom Policy, введите MyAppToMyAppVersion2MigrationPolicy.
Сохранить файл.
Ссылки:
Zarra, Основные данные Глава 5 стр. 87http://pragprog.com/book/mzcd/core-data
http://www.informit.com/articles/article.aspx?p=1178181&seqNum=7
http://www.timisted.net/blog/archive/core-data-migration/
http://www.cocoabuilder.com/archive/cocoa/286529-core-data-versioning-non-trivial-value-expressions.html
http://www.seattle -ipa.org / 2011/09/ 11 / coredata-and-integer-width-in-ios-5 /
Privat, Pro Core Data для iOS Ch 8 p273