Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data NSFetchRequest for Specific Relationship?

I'm transitioning an existing data model that was previously stored in XML to Core Data, so I'm trying to learn the ropes as properly as possible. Core Data is obviously one of those technologies that isn't going anywhere anytime soon, so I might as well "learn it right."

Take for example a Core Data model with two Entities:

  1. Person
  2. Food

Person has 2 one-to-many relationships with Food:

  1. favoriteFoods (1-to-many)
  2. hatedFoods (1-to-many)

(Both Person and Food are subclasses of NSManagedObject as well.)

In the previous data model, Person maintained two NSArray instance variables. If I wanted favorite foods, I could call:

Person *fred = [[Person alloc] init];    
NSArray *fredsFavorites = fred.favoriteFoods;

Easy squeezy.

I'm reading through the documentation for Core Data, and I can't seem to find the right way to obtain this NSArray given an NSFetchRequest, because I can't define which relationship I want to obtain objects from.

NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:@"Food" inManagedObjectContext:[fred managedObjectContext]]];
[request setIncludesSubentities:NO];
NSArray *fredsFavoriteAndHatedFoods = [[fred managedObjectContext] executeFetchRequest:request error:nil];

This returns all of the Food items stored in both favoriteFoods and hatedFoods. How can I split these up? Surely there's a simple explanation, but I don't currently grasp the concept well enough to explain it in Core Data jargon, thus my Google searches are fruitless.

like image 317
Craig Otis Avatar asked Feb 25 '23 19:02

Craig Otis


1 Answers

The most straightforward way to get it is to simply access the relationship NSSet directly:

NSArray *fredsFavorites = [fred.favoriteFoods allObjects];

(I've shown how to get an NSArray from the resulting NSSet).

Alternatively, if you haven inverse relationship set up (which you should) you could use a fetch request like this:

NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:@"Food" inManagedObjectContext:[fred managedObjectContext]]];
[request setPredicate:[NSPredicate predicateWithFormat:@"ANY personsWithThisAsFavorite == %@", fred]];
NSArray *fredsFavoriteFoods = [[fred managedObjectContext] executeFetchRequest:request error:nil];

This assumes that personsWithThisAsFavorite is the inverse relationship to favoriteFoods. Unless I'm reading your example wrong, favoriteFoods should really be a many-to-many relationship, since a person can have multiple favorite foods, and a food can have multiple people with that food as a favorite.

(Note that I haven't tested this, so the NSPredicate might not be 100% correct)

like image 112
Nick Forge Avatar answered Mar 04 '23 09:03

Nick Forge