2

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

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

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

但是,假设我有这个对象模型和关系

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

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

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

我想加载一个列出所有具有“开发人员”角色的员工的 UITableView,并且我想使用 NSFetchedResultsController 来执行此操作。

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

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

4

2 回答 2

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使用简单的 keypath 获取实体,roleType== developer然后返回一个对象。走的employees关系Role会给你所有的开发人员。

使用 Core Data 要记住的重要一点是,实体及其关系旨在模拟您的应用程序处理的真实世界对象、事件和条件。您应该设置数据模型以尽可能接近地表示那些真实世界的事物以及它们之间的关系。例如,在现实世界中,developer只是一个角色,所以它应该由对象图中的一个对象来表示。在现实世界中,很多员工都可以扮演开发者的角色,所以两者之间的关系Employees应该RolesEmployee<<-->Role

您的模型越接近现实,您的应用程序就越容易在各个方面编写。

于 2011-08-17T18:38:14.740 回答
1

我不确定我是否理解您的问题,但是如果您想将 NSFetchedResultsController 与 UITableView 一起使用,则必须使用 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,所以我无法测试代码的有效性,但它应该是正确的。

于 2011-08-17T15:30:01.483 回答