核心数据获取属性和 NSFetchedResultsController

发布于 11-29 19:07 字数 488 浏览 3 评论 0原文

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

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

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

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

公司(一对多)团队(一对多)员工(一对一)角色

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

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

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

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

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

I read this in the core data programming guide:

In many cases, your initial fetch retrieves a starting node in the object graph and thereafter you do not execute fetch requests, you simply follow relationships.

This makes sense if everything is linked to one object.

However, say i have this object model and relationship

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

Say I load my Company at the start with a fetch request. I then have access to a set of Teams, and in each Team i have a set of Employees.

(this is all hypothetical, but my app follows the same model)

I want to load a UITableView that lists all Employees which have a Role of 'developer', and I want to do this using an NSFetchedResultsController.

I would like to create a fetched property on Company that returns all 'developers'. Which is easy enough.

How would I link this fetched property to NSFetchedResultsController ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

So尛奶瓶2024-12-06 19:07:02

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

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

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

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

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

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

现在您有一个 Role 实体,可以将相同的角色附加到许多员工。现在,您可以使用 roleType== Developer 的简单键路径获取 Role 实体,并返回一个对象。遍历Roleemployees 关系将为您提供所有开发人员员工。

使用核心数据时要记住的重要一点是,实体及其关系旨在模拟您的应用程序处理的现实世界对象、事件和条件。您应该设置数据模型以尽可能接近地表示那些现实世界的事物以及它们之间的关系。例如,在现实世界中,开发人员只是一种角色,因此它应该仅由对象图中的一个对象表示。在现实世界中,许多员工都可以担任开发人员的角色,因此EmployeesRoles之间的关系应该是Employee<<-->RoleEmployee<<-->Role代码>.

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

What the documentation is talking about is that you use a fetch to find a set of managed objects based on some attribute and then you find all the related objects by walking the relationships. This differers significantly from how you would find data in a relational database. Since relationships are hardcoded as the object graph is built, walking them is very, very fast compared to fetching and you can model arbitrary relationships.

You seldom, if ever, used fetched properties to find a managed object you could just walk to. Fetched properties are used to find objects you can't walk to such as objects stored in another persistent store file.

To walk relationships you use keypaths. E.g. to find all employees of a particular company in your model, you would use a key path of teams.employees and you would start with a particular company object. To find developers, you would walk the path to the Role attribute that holds the developer value, something like: team.employees.role.roleType.

In your particular case, if you want a table with all developers, you wouldn't set the fetch to the Company entity but to the Employee entity. The you would use a predicate with a keypath e.g. role.roleType== developer. If you wanted all the developers in a certain company you would use a predicate like: `role.roleType== developer AND team.company.name == aCompanyName.

However, it would be even better to adjust your model like this:

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

Now you have a Role entity that can attach the same role to many employees. Now you can fetch on the Role entity with a simple keypath of roleType== developer and you get one object back. Walking the employees relationship of Role would give you all developer employees.

The important thing to remember with Core Data is that the entities and their relationships are meant to simulate the real-world objects, events and conditions that your app deals with. You should set up the data model to as closely as possible represent those real-world things and the relationships between them. E.g. In the real world, developer is just one role so it should be represented by just one object in the object graph. In the real world, many employees could fulfill the role of developer so the relationship between Employees and Roles should be Employee<<-->Role.

The more closely your model simulates reality, the easier you app becomes to write in all regards.

半暖夏伤2024-12-06 19:07:02

我不确定我是否理解你的问题,但是如果你想将 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,所以我无法测试代码有效性,但是它应该是对的。

I am not sure I understood your question, but if you want to use a NSFetchedResultsController with UITableView you have to use a NSFetchRequest, you cannot just follow relationship, which is use faulting.

It seems you already have a fetch request, for use it with a fetched controller you have to pass such request to the NSFetchedResultsController.

However you can get NSFetchedPropertyDescription by looking into the entity description, and its properties:

NSEntityDescription *entityDescription = .....

Then you can call properties and cycle all the array until you find your property:

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];

I do not have my Mac right now so I cannot test for code validity, however it should be right.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文