8

在使用 Core Data 的多对关系时,这是一个长期存在的问题,很难根据与实体的一对多关系的数量对实体上NSSortDescriptor的获取请求进行排序。这在与 a 结合使用时特别有用。通常将排序描述符初始化为:ParentchildrenChildNSFetchedResultsController

NSSortDescriptor *sortByNumberOfChildren = [[NSSortDescriptor alloc] initWithKey:@"children.@count" ascending:NO];

导致异常'Keypath containing KVC aggregate where there shouldn't be one; failed to handle children.@count

iOS 6.1上,我通过将 KVO 访问器-countOf<Key>作为属性添加到我的托管对象模型作为整数类型发现了一个修复。我没有在我的NSManagedObject子类中为这个属性实现任何东西,因为所有的魔法似乎都发生在幕后。(见https://stackoverflow.com/a/15546371/2042527)。

但是,这在iOS 6.0上不起作用。在这里,我发现将以下方法添加到您的NSManagedObject子类可以解决问题:

- (NSUInteger)countOfChildren{
      return [self.children count];
  }

添加两者并不能解决两个 SDK 中的问题。相反,它破坏了修复。

有没有人知道为什么会发生这种情况以及为什么两者之间存在差异,尽管没有提到 iOS 6.0 和 iOS 6.1 之间对 Core Data 或 Foundation 的更改。

4

1 回答 1

7

我认为通过说“包含不应该有的 KVC 聚合的 Keypath;未能处理 children.@count”Core Data 想告诉您它不支持这种排序描述符。这很可能是因为当支持 SQLite 存储收到您的 fetch 请求时,它必须生成执行 fetch 请求所描述的 SQL。“children.@count”的情况实际上比人们想象的要复杂得多。

覆盖 -countOfChildren 的“修复”并不是真正的修复。让我们假设这解决了问题,然后 -countOfChilden 将在每个父级上调用。当您第一次访问 self.children 时,Core Data 需要执行一个 SQL 查询来确定(至少)孩子的主键,创建 NSManagedObjectIDs、NSManagedObjects 并返回结果。如果这有效,那么您会看到非常糟糕的性能。

您的问题有几种解决方案。

1.将子计数存储在持久属性中

只需向父实体添加一个属性(名称:cachedCountOfChildren,类型:64 位整数)。在您的控制器层(不在您的模型层)中,每次将子项分配给父项时,将 cachedCountOfChildren 递增 1,并在每次从父项中删除子项时递减 cachedCountOfChildren。然后在排序描述符键中使用 cachedCountOfChildren。这会有很好的表现。

2.使用字典结果

将 NSFetchRequest 的 resultType 设置为 NSDictionaryResultType。这将导致 -executeFetchRequest:error: 返回 NSDictionaries 而不是 NSManagedObjects。带有 NSDictionaryResultType 的 NSFetchRequest 可以做不同的事情。例如,您可以使用 setPropertiesToGroupBy 和 NSExpression (...)。请查看 WWDC 会议“Using iCloud with Core Data (2012)”(从幻灯片 122 开始)以供参考。基本上,它们向您展示了如何构造一个请求,该请求将返回一个包含具有此结构的字典的数组:

(
 {
  countOfChildren = 1;
  parentName = "hello";
 },
 {
  countOfChildren = 134;
  parentName = "dsdsd";
 },
 {
  countOfChildren = 2;
  parentName = "sdd";
 }
)

如您所见,您将得到未排序的结果。但是通过 countOfChildren 对这个数组进行排序可以非常有效地在内存中完成。在这种情况下,Core Data 生成的 SQL 也将非常有效,您将能够准确指定字典应包含哪些属性。所以结果也应该是非常有效的内存。此解决方案的优点是您不必跟踪 countOfChildren。

您必须根据自己的情况决定哪种解决方案最适合自己。

于 2013-09-20T16:29:08.607 回答