gpt4 book ai didi

xcode - 核心数据更改属性从整数 16 到整数 32

转载 作者:行者123 更新时间:2023-12-04 18:30:55 26 4
gpt4 key购买 nike

我有一个非常严重的问题。该应用程序已上线,但不幸的是它在 iOS 5 上失败了,我需要发布更新。

问题是少数实体的ID列在整数16中,但我需要更改为整数32。

这显然是我的错误,模型是很久以前创建的,只是被重用了。令我惊讶的是(现在)在 iOS 4 上,Core Data 中的整数 16 可以轻松地将数字保持在 500 000(错误?)

应用程序已上线,是否成功,Core Data 还用于保存用户的分数、成就等,我不想删除这些内容,迫使他们重新安装应用程序。简单地将不同实体中的大约十个属性从整数 16 更改为整数 32 的最佳方法是什么?

当然,我知道这些属性的名称和实体。

如果我只是在 xcdatamodeld 文件中更改这些属性的 Type 列,它将对新用户起作用,但是对于现有用户呢,他们的 Documents 文件夹中已经有 sqlite 文件。我相信我需要以某种方式更改持久存储协调器。

还有你对性能有什么看法,大约有 10 个属性要从 16 更改为 32,但通常情况下,Core Data 内部有超过 100 000 个对象。

问候

最佳答案

背景
以前版本的应用程序在 Core Data 中将属性设置为 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

打开右 Pane 检查器,版本化核心数据模型当前从 MyApp 更改为 MyAppVersion2。
在左 Pane 文件导航器中,绿色复选标记从 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
下面的示例转换一个实体“Environment”,它具有整数属性“FeedID”和字符串属性“title”。
- (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
在窗口中,显示右侧实用程序 Pane 。
在窗口中,选择实体映射 EnvironmentToEnvironment
在右侧实体映射中,选择自定义策略输入 MyAppToMyAppVersion2MigrationPolicy。
保存存档。

引用文献:

Zarra,核心数据第 5 章第 87 页 http://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 for iOS Ch 8 p273

关于xcode - 核心数据更改属性从整数 16 到整数 32,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7765300/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com