核心数据关系 NSOrderedSet 在每个设备上返回不同的顺序

Core Data Relationship NSOrderedSet returning different order on each device

我的数据模型中有几个一对多关系。在每种情况下,重要的是从模型中检索数据的顺序与插入数据的顺序相匹配。我在每个关系的检查器中勾选了 'Ordered' 框。我添加数据如下:

NSMutableOrderedSet *set = [destinationEntity mutableOrderedSetValueForKey:relationshipKey];
[set addObject:sourceEntity];
[CoreDataFunctions saveEntity:destinationEntity];

我随后按如下方式检索集合:

NSOrderedSet *set = [sourceEntity valueForKey:relationshipKey];

在添加数据的设备上,这工作正常 - 我可以添加多个实体,它们总是以正确的顺序显示。问题在于,在通过 iCloud 同步接收数据的设备上,该集合以不同的顺序返回。请注意,顺序始终相同,但与在原始设备上输入的顺序不同。

为了解决这个问题,我添加了一个 'order' 属性,在将对象插入集合时,该属性由一个递增的整数填充。然后,我可以在从数据模型中检索后按该键对集合进行排序。但是,如果 NSOrderedSet 没有以可预测的顺序返回,我不禁觉得有些不对劲。

我想知道这是否与我在设备从 iCloud 接收交易时在日志中看到的一些错误有关。我多次看到以下内容,大概每笔交易一次:

*** ERROR: this process has called an NSArray-taking method, such as initWithArray:, and passed in an NSSet object. This is being worked-around for now, but will soon cause you grief.

我假设这是因为数据模型中的对象是 NSSet 类型,而 Core Data 正在将它们传递给需要 NSArray 的对象。但是,我不知道我能做些什么,或者它是否与这个问题有关。我假设是这样,因为我怀疑 Core Data 正在将 NSOrderedSet 转换为 NSArray 并在此过程中丢失排序。不过我无法确认这一点。

非常感谢收到任何建议!

最可靠的方法是创建一个类似于 BaseEntityAbstract Entity,您的数据模型中的所有其他 class 都从中继承。 BaseEntity 将有一个 dateCreated 属性,您在 NSManagedObject 子 class.

中的 awakeFromInsert 中设置

然后当您执行提取请求时,您可以指定 NSSortDescriptor 以使用 dateCreated 进行排序,这非常快,特别是如果您使用 SQLite.

如果这样做,则可以取消选中 CoreData 中的 ordered 按钮。

编辑:这是托管对象子class:

中排序关系的示例

给定实体 Entity 与 CoreData 生成的关系 属性:

@property (nullable, nonatomic, retain) NSSet<Entity *> *toManyRelationship;

然后您可以创建自己的 属性:

@property (nullable, nonatomic, strong, readonly) NSArray<Entity *> *orderedToManyRelationship;

这是这样实现的:

@dynamic toManyRelationship;

- (NSArray<Entity *> *)orderedToManyRelationship
{
    NSSortDescriptor *dateSorter = [NSSortDescriptor sortDescriptorWithKey:@"dateCreated" ascending:YES];

    return [[self.toManyRelationship allObjects] sortedArrayUsingDescriptors:@[dateSorter]];
}