开发者

core data fetched properties and NSFetchedResultsController

开发者 https://www.devze.com 2023-03-29 05:15 出处:网络
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 re

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 ?


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消