核心数据关系 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 并在此过程中丢失排序。不过我无法确认这一点。
非常感谢收到任何建议!
最可靠的方法是创建一个类似于 BaseEntity
的 Abstract 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]];
}
我的数据模型中有几个一对多关系。在每种情况下,重要的是从模型中检索数据的顺序与插入数据的顺序相匹配。我在每个关系的检查器中勾选了 '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 并在此过程中丢失排序。不过我无法确认这一点。
非常感谢收到任何建议!
最可靠的方法是创建一个类似于 BaseEntity
的 Abstract 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]];
}