I have a Core Data model with three entities: Notification, Group and Customer. These are the relationships between them:
- A customer belongs to many groups and a group can have many customers.
- A notification is sent (belongs) to a group and a group can receive (have) many notifications.
I would like to show all notifications in a UITableView grouped by customer. I have created a NSFetchedResultsController like this:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
fetchRequest.fetchBatchSize = 10;
fetchRequest.predicate = nil;
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Notification"
inManagedObjectContext:self.managedObjectContext];
fetchRequest.entity = entity;
// Default sort descriptors are built in a separate custom method
NSArray *sortDescriptors = [self getDefaultSortDescriptorsForEntity:entity];
fetchRequest.sortDescriptors = sortDescriptors;
return [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:@"group.customers.firstName"
cacheName:nil];
Assuming this is a valid way to retrieve all notifications grouped by customer (I’m not sure about that either) iOS is throwing the following exception:
@"Failed to fetch all Notification objects"
@"Reason: Invalid to many relationship in setPropertiesToFetch: (group.customers.firstName) (NSInvalidArgumentException)"
I have reviewed the relationships again and again to see if something is missing and everything seem to be correct. I can create and delete objects for all entities and links between them are correct as well.
My question is: Is it possible to traverse through several relationships in a sectionNameKeyPath value? How should many-to-many relationships be handled in this kind of scenario?
Yes, you can do this. Just fetch the customers with the FRC and set the
sectionNameKeyPathtonil.Sections
The number of returned results is your number of sections. Populate the section headers with the customer data.
Rows
The number of rows in section would be
customer.notifications.count. To populate the row, make sure thenotificationsare sorted in some way (say, by date) and display them accordingly with something like this:An alternative – recommended – solution is to change the data model. You could associate the notification with all customers directly. That would have the added advantage, that notifications remain associated with the correct customers even if group memberships change.