user2924482
user2924482

Reputation: 9120

CoreData :NSFetchedResultsController one to many to many to many relationship

I working on app were I using core data and the core data object is is show below:

enter image description here Giving theaterName and genreName I want to show the actorsName. Anyone know of a way to build a NSPredicate to do that?

Upvotes: 1

Views: 232

Answers (1)

Raul Rea
Raul Rea

Reputation: 136

You can use SUBQUERY to build NSPredicates that go deep into "to many" relationships:

    // Set predicate
NSPredicate *requestPredicate = [NSPredicate predicateWithFormat:@"SUBQUERY(genres, $g, ANY $g.movies.name == %@).@count != 0",  @"Batman vs Superman"];
[fetchRequest setPredicate:requestPredicate];

UPDATE

Based on your updated example, you'll need nested subqueries like this:

 NSPredicate *requestPredicate = [NSPredicate predicateWithFormat:@"SUBQUERY(movies, $m, ANY $m.genres.name == %@).@count != 0 AND SUBQUERY(movies, $m, SUBQUERY($m.genres, $g, ANY $g.theaters.name == %@).@count != 0).@count != 0", @"Action", @"Harkins"];

Here is a sample Cast entity fetch:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Cast" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO];
NSArray *sortDescriptors = @[sortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
// Set predicate
NSPredicate *requestPredicate = [NSPredicate predicateWithFormat:@"SUBQUERY(movies, $m, ANY $m.genres.name == %@).@count != 0 AND SUBQUERY(movies, $m, SUBQUERY($m.genres, $g, ANY $g.theaters.name == %@).@count != 0).@count != 0", @"Action", @"Harkins"];
[fetchRequest setPredicate:requestPredicate];
// Fetch
NSError *error = nil;
if (![aFetchedResultsController performFetch:&error]) {
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}
// Check fetched objects
NSArray *fetchedObjects = [aFetchedResultsController fetchedObjects];
for (Cast *eachCast in fetchedObjects) {
    NSLog(@"Each Cast name: %@", eachCast.name);
}

Just replace @"Action" with the desired Genre name and @"Harkins" with the Theater name.

Here is how I setup the core data model: Core data model setup

Upvotes: 3

Related Questions