NSSortDescriptor按照Core Data To-Many关系中的项目数排序 [英] NSSortDescriptor to sort by number of items in Core Data To-Many Relationships

查看:165
本文介绍了NSSortDescriptor按照Core Data To-Many关系中的项目数排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Core Data多对多关系时,很难使用上的 NSSortDescriptor 对获取请求进行排序,这是一个长期存在的问题。父实体基于的数量与是一对多关系$ c> entity。这在与 NSFetchedResultsController 的组合中尤其有用。通常初始化排序描述符为:

It's a long standing problem when using Core Data to-many-relationships that it is very hard to sort a fetch request using NSSortDescriptor on a Parent entity based on the number of children are in a one-to-many relationship to a Child entity. This is especially useful in combination with a NSFetchedResultsController. Typically initializing the sort descriptor as:

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

导致一个异常'Keypath包含KVC聚合,一;未能处理孩子。@ count

iOS 6.1 ,我发现通过添加KVO访问器 -countOf< Key> 作为整数类型的我的托管对象模型的属性。我没有在我的 NSManagedObject 子类中为这个属性实现任何东西,因为所有的魔力似乎都发生在底层。 (请参阅 http://stackoverflow.com/a/15546371/2042527 )。

On iOS 6.1, I discovered a fix by adding the KVO accessor -countOf<Key> as an attribute to my managed object model as an integer type. I did NOT implement anything for this attribute in my NSManagedObject subclass, as all the magic seems to happen under the hood. (see http://stackoverflow.com/a/15546371/2042527).

但是,这不适用于 iOS 6.0 。这里我发现,添加以下方法到您的 NSManagedObject 子类解决了问题:

However, this does not work on iOS 6.0. Here I found that adding the following method to your NSManagedObject subclass resolves the problem:

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

同时添加 SDK。相反,它打破了修复。

Adding both does not fix the problem in both SDKs. On the contrary, it breaks the fix.

有没有人有一个线索为什么这是发生,为什么两者之间有区别,eventhough没有提到的变化iOS 6.0和iOS 6.1之间的核心数据或基础。

Does anyone have a clue why this is happening and why there is a difference between both, eventhough there is no mention of changes to Core Data or Foundation between iOS 6.0 and iOS 6.1.

推荐答案

我认为通过说Keypath包含KVC聚合, t是一个;无法处理孩子。@ countCore Data想告诉你它不支持这种类型的描述符。这很可能是因为当SQLite存储接收到您的获取请求时,它必须生成执行获取请求描述的SQL。

I think that by saying "Keypath containing KVC aggregate where there shouldn't be one; failed to handle children.@count" Core Data wants to tell you that it does not support this kind of sort descriptor. This is very likely because when the backing SQLite store receives your fetch request it has to generate SQL that does what the fetch request describes. The case of "children.@count" is actually more complex under the hood than one might think.

覆盖-countOfChildren的修复并不是一个修复。让我们假设一秒钟这解决了问题,然后-countOfChilden将在每个父。当您首次访问self.children时,Core Data需要执行SQL查询,以确定(至少)子项的主键,创建NSManagedObjectIDs和NSManagedObjects并返回结果。

The "fix" with overriding -countOfChildren is not really a fix. Let's assume for a second that this fixes the problem then -countOfChilden would be called on every Parent. When you first access self.children then Core Data needs to execute a SQL query that determines (at least) the primary keys of the children, create NSManagedObjectIDs, NSManagedObjects and return the result. If this worked then you would see very bad performance.

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

There are several solutions to your problem.

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

Simply add a attribute (name: cachedCountOfChildren, type: Integer 64 bit) to your Parent entity. In your controller layer (NOT IN YOUR MODEL LAYER) increment cachedCountOfChildren by 1 every time you assign a child to a parent and decrement cachedCountOfChildren every time you remove a child from a parent. Then you use cachedCountOfChildren in your sort descriptor key. This will have great performance.

2。使用字典结果

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

Set the resultType of your NSFetchRequest to NSDictionaryResultType. This will cause -executeFetchRequest:error: to return NSDictionaries instead of NSManagedObjects. A NSFetchRequest with a NSDictionaryResultType can do different things. For example you can use setPropertiesToGroupBy and NSExpression (...). Please look at the WWDC session "Using iCloud with Core Data (2012)" (starting at slide 122) for reference. Basically they show you how to construct a request that will return an array which contains dictionaries that have this structure:

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

正如你所看到的,你会得到一个未排序的结果。但是通过countOfChildren排序这个数组可以在内存中非常有效地完成。在这种情况下,Core Data生成的SQL也非常高效,您将能够精确指定字典应包含的属性。所以结果也应该是非常记忆效率。这个解决方案的优点是你不必跟踪countOfChildren。

As you can see you will get a unsorted result back. But sorting this array by countOfChildren can be done in memory very efficiently. The generated SQL by Core Data will also be very efficient in this case and you will be able to specify exactly which attributes the dictionaries should contain. So the result should also be very memory efficient. This solution has the advantage that you do not have to keep track of the countOfChildren.

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

You have to decide which solution is best for yourself depending your your situation.

这篇关于NSSortDescriptor按照Core Data To-Many关系中的项目数排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆