Question

I have a pretty complicated Core Data model in my Xcode project. For simplicity, I will just say here that my model includes Games which have a to-many relationship to Teams which each have a to-many relationship to Players. All three of these entities have their own properties as well (eg gameLocation, teamScore, playerNumber, etc).

My database is fully populated, thanks to a mass GET request made by Restkit to a Ruby on Rails built website. So now, I want to start working with this data - displaying and modifying it. I know this involves fetch requests and predicates, but I don't know when and where I need to perform these fetches. Can I fetch a Game and then access everything associated with that Game from that Game? For example, here is my code for fetching all of the Games that are scheduled for today:

NSFetchRequest *request = [[NSFetchRequest alloc] init];

NSEntityDescription *desc = [NSEntityDescription entityForName:@"Game" inManagedObjectContext:self.managedObjectContext];
[request setEntity:desc];

NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"time" ascending:YES];
[request setSortDescriptors:@[sort]];

/*** some code that determines the values for variables 'todaysDate' and 'tomorrowsDate' ***/

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(date >= %@) AND (date < %@)", todaysDate, tomorrowsDate];
[request setPredicate:predicate];

NSError *error = nil;
self.games = [self.managedObjectContext executeFetchRequest:request error:&error];

But now what? What is the best way to access the Teams of those Games? Do I need more fetch requests or is that inefficient? I tried something like this, but it doesn't seem right

Game *game1 = [self.games objectAtIndex:0];
NSMutableSet *game1Teams = [game1 mutableSetValueForKey:@"gameTeams"];

Not only the Teams, but how do I access the scores of the Teams of those Games? The Players of those Games? etc...

(maybe a reference to a tutorial or some example code would be a good place for me since I'm sure this is trivial stuff)

Was it helpful?

Solution

The key phrase is this:

"Can I fetch a Game and then access everything associated with that Game from that Game?"

The answer is "Yes".

You traverse the entire "tree" based on a single fetch request, by simply referencing the pointers to sets (or whatever) that are defined within your entities, and allow Core Data to handle when it needs to load various entities.

This made no sense to me to begin with but when I quit fighting it I found it to be so much easier than I thought.

This is from a project of mine:

@property (nonatomic, retain) NSString * goalName;
@property (nonatomic, retain) NSData * goalPicture;
@property (nonatomic, retain) NSNumber * indexOrder;
@property (nonatomic, retain) NSNumber * wordPicture;
@property (nonatomic, retain) NSSet *item;
@property (nonatomic, retain) User *user;
@property (nonatomic, retain) NSSet *video;

In my case, the user is the top level node in the tree, and there can be multiple items under each goal as well as multiple videos.

Once I have done a fetch request for a given User, I can access the goals for that user with an NSSet in the user entity. So, I get the set of goals with:

NSSet *goals = userObj.goal;
Goal *g = [goals anyObject]; // for example.

Then, if I want the items "contained" within a given goal:

NSSet *items = g.items;
Item *i = [items anyObject];

and so on. The important thing is that core data will load the entities efficiently. If you have 10,000 items attached to a particular goal you don't have to worry about those getting fetched until they're actually needed...

OTHER TIPS

This link will be useful for you

https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreData/cdProgrammingGuide.html

specifically, faulting is what you seem to be asking about. In terms of references (eg, a reference to a list of Player from a Team) core data will not fetch the whole set of data. It instead has a thing called a fault. When you then try to access the player (eg [team.players objectAtIndex:10] or whatever) CoreData will scurry away and fetch the actual data for that object.

Understanding this, and also how and when to turn an object back into a fault to clean up memory should go a long way to helping answer your question.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top