Core Data: Can relationship be used for sectionNameKeyPath?
I am trying to do exactly same thing as 开发者_StackOverflow社区post in NSFetchResultsController + sectionNameKeyPath + section order, i.e. basically use 2 tables, let's say Categories <-->> Events. Category table consists of category field only, while Event consists of name, dateTimestamp. I defined relationship 'category' in Events table and try to use that relationship as sectionNameKeyPath when creating fetchedResultsController:
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"category.category" cacheName:@"Root"];
Finally, I pre-populated Category table with some categories upon loading of the app (and verified with .dump that table is populated correctly)
Yet, I simulator fails on:
return [[self.fetchedResultsController sections] count];
I did extensive search and most people either suggest using one of the fields in the table as sectionNameKeyPath (this works!) or transient property (works too!) However, I just want to use relationship as it seems very logical to me in this case where events belong to some categories and there could be categories without events. Am I wrong in my assumption that relationship can be used as sectionNameKeyPath? The original link at the top of the question suggests it works, but guy does not know why or how. Documentation is very weak on what can be used as sectionNameKeyPath, so any help will be highly appreciated.
A relationship gets you a pointer to a managed object. It seems logical, though, that the sectionNameKeyPath
parameter should be a key path that leads to a string, since NSFetchedResultsSectionInfo's name
property is a string. The fetched results controller will follow that key path for each fetched object and group the objects into sections based on what they return for that key path, and it'll also use those strings as the names of their respective sections. You can't use a managed object for the name -- you have to use some string property of the managed object.
So, your Category entity must have an attribute that distinguishes one category from another, right? Use that as the key path and (as you've seen) everything will work out.
BTW, I think it's useful to try to get out of the database (rows/fields) mindset and try to think in object-oriented terms like entity and attribute. A big selling point of Core Data is that it provides an abstraction layer that hides the storage mechanism. Thinking in terms of tables is like thinking about blocks and sectors when you're reading or writing a file.
Caleb, thank you for your answer. I do believe my understanding was wrong to some degree. What I had was an entity Category and entity Event. Category has a string field 'category', thus 'category.category' path (first 'category' is relationship in the Event entity)
What I did not take in account, though, is that if there are no events, fetchresultscontroller cannot fetch anything (similar to 'left join')
What I wanted is to show categories even if there are no events. Relationship 'category' will not return anything in this case as there is nothing to return/sort/categorize.
What I had to do (wrong or right - not sure yet) is to treat [managed] object created from Category entity as a separate object in case there are no events and place in the table. When there is one event per category, I can switch to the original method of [automatic] showing events sorted by categories.
This is interesting issue of starting point (empty entities with relationships) where I feel core data is more confusing than traditional relationship database. I also believe that's why all books/articles/reports carefully stay away from this topic. In other words, I could not find analog of "left join" in core data. May be I am wrong because I am relatively new to all this. Below is the description of the entities:
Category <-->> Event
Category - parent Category.category - attribute of type String Category.event - relationship to Event entity
Event - child Event.name - attribute of type String Event.category - relationship to Category entity
Each event belongs to one category. Category may have multiple events. Categories should be shown even if there are no events for this category.
I was trying to put Events under fetchresultscontroller. May be I should switch to Category first and then calculate cell based on category.event relationship, not the other way around - did not try that yet.
精彩评论