Core data NSSortDescriptor,用于根据核心数据中的项目数对多个关系进行排序
在对多个关系使用核心数据时,一个长期存在的问题是,很难使用Core data NSSortDescriptor,用于根据核心数据中的项目数对多个关系进行排序,core-data,ios6,nsfetchedresultscontroller,key-value-observing,nssortdescriptor,Core Data,Ios6,Nsfetchedresultscontroller,Key Value Observing,Nssortdescriptor,在对多个关系使用核心数据时,一个长期存在的问题是,很难使用NSSortDescriptor对父实体上的获取请求进行排序,这是基于子实体与子实体处于一对多关系的子实体的数量。这在与NSFetchedResultsController结合使用时特别有用。通常将排序描述符初始化为: NSSortDescriptor *sortByNumberOfChildren = [[NSSortDescriptor alloc] initWithKey:@"children.@count" ascending:N
NSSortDescriptor
对父实体上的获取请求进行排序,这是基于子实体与子实体处于一对多关系的子实体的数量。这在与NSFetchedResultsController结合使用时特别有用。通常将排序描述符初始化为:
NSSortDescriptor *sortByNumberOfChildren = [[NSSortDescriptor alloc] initWithKey:@"children.@count" ascending:NO];
导致异常“包含KVC聚合的关键路径,其中不应该有一个;无法处理子项。@count
在iOS 6.1上,我发现了一个修复方法,将KVO访问器-countOf
作为一个整型属性添加到我的托管对象模型中。在我的NSManagedObject
子类中,我没有为这个属性实现任何东西,因为所有的魔法似乎都发生在幕后。(见附件)
但是,这在iOS 6.0上不起作用。在这里,我发现将以下方法添加到NSManagedObject
子类可以解决问题:
- (NSUInteger)countOfChildren{
return [self.children count];
}
将两者相加不会解决两个SDK中的问题。相反,它打破了固定
有没有人知道为什么会发生这样的事情,为什么两者之间存在差异,即使没有提到在IOS 6和IOS 6.1之间的核心数据或基础的改变。 < P>我认为,“KKY路径包含KVC集合,不应该有一个;没有处理孩子。”核心数据想告诉您,它不支持这种排序描述符。这很可能是因为当后台SQLite存储接收到您的获取请求时,它必须生成符合获取请求描述的SQL。“children.@count”的情况实际上比人们想象的要复杂得多
覆盖countOfChildren的“修复”并不是真正的修复。让我们先假设一下,这解决了问题,然后将对每个家长调用countOfChilden。当您首次访问self.children时,核心数据需要执行SQL查询,该查询确定(至少)子项的主键,创建NSManagedObjects、NSManagedObjects并返回结果。如果这起作用,那么您将看到非常糟糕的性能
你的问题有几种解决办法
1。将子计数存储在持久属性中
只需向父实体添加一个属性(名称:cachedCountOfChildren,类型:Integer 64位)。在控制器层(而不是模型层)中,每次将子对象指定给父对象时,将cachedCountOfChildren增加1,每次从父对象中删除子对象时,将cachedCountOfChildren减少1。然后在排序描述符键中使用cachedCountOfChildren。这将有很好的表现
2。使用字典结果
将NSFetchRequest的resultType设置为NSDictionaryResultType。这将导致-executeFetchRequest:error:返回NSDictionaries而不是NSManagedObjects。具有NSDictionaryResultType的NSFetchRequest可以执行不同的操作。例如,您可以使用setPropertiesToGroupBy和NSExpression(…)。请查看WWDC课程“使用iCloud和核心数据(2012)”(从幻灯片122开始)以供参考。基本上,它们向您展示了如何构造一个请求,该请求将返回一个数组,该数组包含具有以下结构的词典:
(
{
countOfChildren = 1;
parentName = "hello";
},
{
countOfChildren = 134;
parentName = "dsdsd";
},
{
countOfChildren = 2;
parentName = "sdd";
}
)
如您所见,您将返回未排序的结果。但按孩子数对数组进行排序可以在内存中非常有效地完成。在这种情况下,由核心数据生成的SQL也将非常有效,您将能够准确地指定字典应该包含哪些属性。因此,结果也应该是非常高效的内存。这个解决方案的优点是你不必记录孩子的数量
您必须根据自己的情况决定哪种解决方案最适合自己。您将此添加到了NSManagedObjectModel
?很难看出它是如何编译的,更不用说工作了。NSManagedObjectModel
与其他类没有任何关系。对不起,我的错,我的意思是第二次也是NSManagedObject
子类。我已经纠正了这个错误。这不是对你的确切问题的解决方案,而是对它的另一种看法:把孩子们带回来,数一数不同父母的数目如何?也许这对您有帮助。为什么不在NSManagedObject子类(即模型层)上实现它?实现什么?1或2?我想知道为什么您为1编写了以下内容:在控制器层(而不是模型层)中,每次您…时,将cachedCountOfChildren增加1。因为在完美的世界中,您的NSManagedObject应该非常简单。这是因为许多原因(性能、复杂性等)。在你的子类中正确地做聪明的事情是非常困难的。例如,当一个对象由于内存中的所有属性都设置为nil而变成故障时,您会收到一个针对“children”的KVO通知。并非所有属性更改都是由您或用户引起的更改。上下文可以将对象转化为错误,您可以更改子对象的计数。