Core Data迁移后如何保持数据有序?

Posted

技术标签:

【中文标题】Core Data迁移后如何保持数据有序?【英文标题】:How to keep data ordering after Core Data migration? 【发布时间】:2016-11-16 06:23:53 【问题描述】:

在当前项目中,我有一组使用 Core Data 存储的对象。 现在我需要向 DataModel 添加一个字段。

我已添加它,创建了新的映射模型,将其设置为当前并成功迁移到新的数据模型。一切正常,但是..我的数据顺序丢失了。 由于某些奇怪的原因,以前的开发人员没有为数据模型创建任何 order 属性,并且在获取数据时会自动排序(我相信按 id..)

使用映射模型迁移到新数据模型后,每次迁移后我都会对数据进行随机排序。 并且一些与这些数据的顺序相关的应用逻辑现在被破坏了。

如何解决这个问题? 可以根据旧 ID 创建订单属性吗? 或者我如何使用 id 进行迁移?

已经花了一天时间解决这个问题,但没有找到解决方案。

非常感谢! 亚历克斯。

请求的检索数据代码:

NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Area" inManagedObjectContext:[self context]];

NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];

NSError *error;
return  [[[self context] executeFetchRequest:request error:&error] mutableCopy];

【问题讨论】:

您能否发布有关如何检索数据的代码? @jjatie 当然,将其添加到问题文本中 您没有提供NSSortDescriptorNSPredicate 来限制和排序结果。您需要这样做才能为您提供managedObjectContext 排序结果。 @jjatie 感谢您的建议!我没有可以对这些数据进行排序的属性。在迁移之前,它按照插入的顺序返回,并且这种行为是正确的。我相信它是按内部数据 ID 排序的。迁移后数据以随机顺序插入。第一个记录可以是一次迁移后的第 3 个记录,也可以是另一个迁移后的第 2 个记录。我的目标是通过在迁移之前引入一些基于数据顺序的排序属性并使用它来保持当前顺序,或者按照数据顺序进行迁移。 你之前很幸运,结果以与插入相同的顺序返回;对此没有任何保证。如果您需要按日期排序,请拥有一个日期属性并为其创建一个排序描述符。您可以按任何存在的属性进行排序。 【参考方案1】:

最简单的方法是不依赖于一些内部排序。当您访问数据时,将排序描述符添加到 fetch 请求中。

还要确保您的排序结果按顺序处理,请使用老式循环 for (int i = 0; i < array.count; i++) 而不是枚举器 for (id a in array)

【讨论】:

使用枚举器。从文档中:“如果您要枚举有序集合,则枚举按该顺序进行。对于 NSArray,这意味着第一遍将用于索引 0 处的对象,第二遍用于索引 1 处的对象,等等。”。 谢谢弗拉基米尔!我已经用老式的“for”循环尝试了你的解决方案,数据的顺序仍然不正确。我不能按某些属性对项目进行排序的原因 - 我没有这个属性。当然,我可以添加它,但我需要为以前的用户保持数据顺序并尝试找出它是如何实现的。 @Willeke 关键字是“有序”。我绝对不确定使用枚举器 NSArray 是按顺序扫描的。当您需要处理数组的每个元素时这并不重要,但是当顺序很重要时,我更喜欢使用“旧”循环 - 不要依赖编译器。 @AlexanderStepanov 您需要找到一种方法,如何重现“旧”元素顺序。它可以通过请求中的排序描述符或用于后处理(重新排序)请求后获得的数据的一些人工算法来实现。请注意 - 当您在迁移期间添加新字段时,会创建额外的数据库文件和您的最终请求;结果实际上是对旧表和新表中的数据进行一些内部操作的结果。 @ВладимирВодолазкий 1. 文档说顺序是数组的顺序。 2. 顺序不是由编译器决定的。它由NSArrayNSFastEnumeration 的实现决定。 3.快速枚举速度更快。 4. 苹果推荐快速枚举。 5.我从经验中知道:订单没问题。【参考方案2】:

终于知道怎么解决了。

我尝试创建自定义策略,发现数据以正确的顺序传递给它(就像它在迁移之前存储在 CoreData 中一样) 这是创建自定义策略的方法:Core Data versioning and migrating with custom policy

在这之后事情变得简单了。我创建了 sortOrder 字段,并为自定义策略中的每个实体增加它,并将其设置为我的实体的新字段 sortOrder

感谢大家的帮助。

代码如下:

- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance entityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError **)error 
MyEntity* myEntity = (MyEntity*)[NSEntityDescription insertNewObjectForEntityForName:[mapping destinationEntityName] inManagedObjectContext:[manager destinationContext]];

myEntity.myProp1 = [sInstance valueForKey:@"myProp1"];
//a lot of properties here..
//here is the solution - set sortOrder. Is is the property of custom policy class - one instance of this class is used for each entity migration
area.sortOrder = sortOrder;
int value = [sortOrder intValue];
sortOrder = [NSNumber numberWithInteger:value + 1];

[manager associateSourceInstance:sInstance withDestinationInstance:myEntity forEntityMapping:mapping];

return YES; 

然后我只是在我的视图中对项目进行排序。

【讨论】:

以上是关于Core Data迁移后如何保持数据有序?的主要内容,如果未能解决你的问题,请参考以下文章

轻量级迁移后如何从 Core Data 中删除数据

在后台使用 Core Data 加密

在 Core Data 迁移后插入数据

如何让字典保持有序

当涉及多个设备时,Core Data iCloud 迁移“丢失”数据

Core Data 轻量级迁移后执行自定义代码