核心数据获取跨一对一关系的请求谓词过滤

时间:2012-08-26 19:55:49

标签: objective-c ios core-data

我有以下模型图:

                  +-----------+     +-----------+
                  | Container |     |   Group   |
                  +-----------+     +-----------+
                  |  groups   |<-->>| container |
                  +-----------+     +-----------+
                        ^                 ^
                        |                 |
+-----------+     +-----------+     +-----------+     +---------+
|   Owner   |     |  ToyBox   |     |  ToyType  |     |  Item   |
+-----------+     +-----------+     +-----------+     +---------+
|  toyBox   |<--->|   owner   |     |   items   |<-->>| toyType |
+-----------+     +-----------+     +-----------+     +---------+

在UITableView中,我将显示一个列表项目。在这种情况下,我只想显示属于特定所有者的项目。为此,我将使用NSFetchedResultsController来显示项目。这意味着我需要使用适当的NSPredicate创建一个NSFetchRequest,以提供给NSFetchedResultsController。

尝试使用keypath谓词会导致父实体导致异常。这似乎是Apple的错误或不支持的决定。雷达已经提交。此外,我不希望压扁实体。

因此,我试图使用SUBQUERY()执行此操作,如下所示:

NSFetchRequest *itemsFetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Item"];
NSPredicate *itemsPredicate = [NSPredicate predicateWithFormat:@"SUBQUERY(toyItem, $g, SUBQUERY($g.container, $c, SUBQUERY($c.owner, $o, $o = %@).@count > 0).@count > 0).@count > 0", ownerObject];

这会导致以下异常:

Can't have a non-relationship collection element in a subquerySUBQUERY($c.owner, $o, $o == <MLMOOwner: ...

我意识到因为Owner和ToyBox之间的关系是一对一的,所以没有返回集合,这就是问题所在。所以我的问题是:

1)有没有办法强制在子查询中返回集合中的一个关系?
2)如果没有,还有另一种方法可以为获取请求创建这个谓词吗?

1 个答案:

答案 0 :(得分:2)

似乎做你想做的事要简单得多。如果您想要具有给定所有者的所有项目,请从所有者开始并使用关键路径获取关联项目。您不需要谓词。如果你有10罐花生,你想在罐子里找回花生,你不要从所有花生开始,然后根据罐子过滤它们,对吧?你首先得到罐子2,然后你看看它包含的花生。所以这样做:

NSSet *groups = [ownerObject valueForKeyPath:@"toyBox.groups"];

这将为您提供ownerObject拥有的所有群组。您不能仅使用单个密钥路径获取所有项目,因为Group实体没有items属性。通过赋予Group items访问器,您可以让自己的生活更轻松,即使它只返回一个空集。那会让你这样做:

NSSet *items = [ownerObject valueForKeyPath:@"toyBox.groups.items"];

如果您不想向items添加Group属性,则必须从第一个示例中过滤集groups,以便仅选择那些对象ToyType对象。然后,您可以使用该集合上的密钥路径@"items"来获取所需的项目列表。

你必须对实体继承有点小心。你刚刚看到它如何使得更复杂。它还会影响数据的存储方式,即all instances of sub-entities are stored in the same table。因此,如果您有十几个派生自Group的实体(例如ToyType),则所有这些实体的所有实例都会存储在一起。