核心数据获取属性和NSFetchedResultsController

时间:2011-08-17 13:20:01

标签: core-data nsfetchedresultscontroller fetched-property

我在核心数据编程指南中读到了这个:

  

在许多情况下,您的初始提取会检索对象图中的起始节点,然后您不会执行提取请求,只需遵循关系。

如果所有内容都链接到一个对象,这是有道理的。

然而,说我有这个对象模型和关系

Company (one to many) Team (one to many) Employee (one to one) Role

假设我在开始时使用获取请求加载我的公司。然后我可以访问一组团队,在每个团队中我都有一组员工。

(这是假设,但我的应用程序遵循相同的模型)

我想加载一个UITableView,列出所有具有'developer'角色的Employees,我想使用NSFetchedResultsController来做这件事。

我想在公司上创建一个返回所有“开发者”的获取属性。这很容易。

如何将此获取的属性链接到NSFetchedResultsController?

2 个答案:

答案 0 :(得分:3)

文档所讨论的是您使用fetch来根据某个属性查找一组托管对象,然后通过遍历关系找到所有相关对象。这与您在关系数据库中查找数据的方式有很大不同。由于在构建对象图时对关系进行了硬编码,因此与获取相比,使用它们非常非常快,并且可以建模任意关系。

您很少(如果有的话)使用获取的属性来查找您可以步行到的托管对象。获取的属性用于查找无法走到的对象,例如存储在另一个持久性存储文件中的对象。

要走路关系,请使用关键路径。例如。要查找模型中特定公司的所有员工,您将使用teams.employees的关键路径,并从一个特定的公司对象开始。要查找开发人员,您可以使用包含Role值的developer属性的路径,例如:team.employees.role.roleType

在您的特定情况下,如果您想要一个包含所有开发人员的表,则不会将提取设置为Company实体,而是设置为Employee实体。您将使用带有键路径的谓词,例如role.roleType== developer。如果您想要某个公司的所有开发人员,您可以使用谓词:`role.roleType == developer AND team.company.name == aCompanyName。

但是,最好像这样调整模型:

Company<-->>Team<-->>Employee<<-->Role

现在您拥有一个Role实体,可以将相同的角色附加到许多员工身上。现在,您可以使用Role的简单关键路径获取roleType== developer实体,并返回一个对象。行走employees的{​​{1}}关系将为您提供所有开发人员员工。

使用Core Data需要记住的重要事项是,实体及其关系旨在模拟应用处理的真实对象,事件和条件。您应该尽可能地将数据模型设置为代表那些真实世界的东西以及它们之间的关系。例如。在现实世界中,Role只是一个角色,因此它应该只由对象图中的一个对象表示。在现实世界中,许多员工可以履行开发人员的角色,因此developerEmployees之间的关系应为Roles

您的模型越接近现实,您的应用就越容易在所有方面进行编写。

答案 1 :(得分:1)

我不确定我理解你的问题,但是如果你想使用带有UITableView的NSFetchedResultsController,你必须使用NSFetchRequest,你不能只关注关系,这是使用错误。

似乎你已经有了一个获取请求,为了将它与一个获取的控制器一起使用,你必须将这样的请求传递给NSFetchedResultsController。

但是,您可以通过查看实体描述及其属性来获取NSFetchedPropertyDescription:

NSEntityDescription *entityDescription = .....

然后你可以调用属性并循环所有数组,直到找到你的属性:

NSArray *allProperties = entityDescription.properties;
NSFetchedPropertiesDescription *myPropertyDescription;
for(NSPropertyDescription *propertyDescription in allProperties) {
  // find it by name or class
  if([propertyDescription isKindOfClass:[NSFetchedPropertyDescription class]])
    myPropertyDescription = (NSFetchedPropertyDescription*)propertyDescription;
}

NSFetchedRequest *fetchRequest = [myPropertyDescription fetchRequest];

        NSFetchedResultsController *myController = [[NSFetchedResultsController alloc]
                                                 initWithFetchRequest:fetchRequest
                                                 managedObjectContext:myManagedObjectContext
                                                 sectionNameKeyPath:nil
                                                 cacheName:myCacheName];

我现在没有Mac,所以我无法测试代码的有效性,但它应该是正确的。