I'm having problems with fetching objects from a one to many relationship. I have two entities "Featured" and "Event", the featured object contains a property of featuredEvents, this is a One-Many relationship, one "Featured" item to many "Events".
Now i need to use an NSFetchedResultsController to return the events featured in the "featuredEvents" relationship. I'm using the following code:
NSFetchedResultsController *fetchedFeaturedEvents;
NSFetchRequest *fetchRequest;
NSError *error = nil;
fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"SDMFeaturedEvent"];
[fetchRequest setSortDescriptors:@[]];
fetchedFeaturedEvents = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:theManagedObjectContext sectionNameKeyPath:nil cacheName:nil];
[fetchedFeaturedEvents performFetch:&error];
if (error) {
NSLog(@"Unable to perform fetch.");
NSLog(@"%@, %@", error, error.localizedDescription);
}
return fetchedFeaturedEvents;
This is great i return the featured event, but i also wish to add a predicate to only return the events in the "featuredEvents" property. So the question is how do i create the predicate?
i basically need all "Events" IN the featuredEvents property of the "Featured" object im making the fetch for, is this possible?
For those who have been having similar issues, i eventually used this approach:
NSFetchRequest *fetchRequest;
NSError *error = nil;
NSArray *fetchedObjects;
NSPredicate *soldOutPredicate;
NSPredicate *criteriaMatchPredicate;
NSCompoundPredicate *fullPredicate;
NSSortDescriptor *usesDescriptor = [[NSSortDescriptor alloc] initWithKey:@"eventDate" ascending:YES];
fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"FeaturedEvent"];
[fetchRequest setSortDescriptors:@[]];
fetchedObjects = [theManagedObjectContext executeFetchRequest:fetchRequest error:&error];
if (error) {
NSLog(@"Unable to perform fetch.");
NSLog(@"%@, %@", error, error.localizedDescription);
}
if ([[NSSDMUserDetails sharedManager]showsCriteraMatchEvents]) {
if ([[NSSDMUserDetails sharedManager]isUserMale]) {
criteriaMatchPredicate = [NSPredicate predicateWithFormat:@"(eventAgeMaleMin <= %@) AND (eventAgeMaleMax >= %@)",[[[NSSUserDetails sharedManager]userAge]stringValue],[[[NSUserDetails sharedManager]userAge]stringValue]];
}
else{
criteriaMatchPredicate = [NSPredicate predicateWithFormat:@"(eventAgeFemaleMin <= %@) AND (eventAgeFemaleMax >= %@)",[[[NSUserDetails sharedManager]userAge]stringValue],[[[NSUserDetails sharedManager]userAge]stringValue]];
}
fullPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[criteriaMatchPredicate]];
}
if (![[NSSDMUserDetails sharedManager]showsSoldOutEvents]) {
if ([[NSSDMUserDetails sharedManager]isUserMale]) {
soldOutPredicate = [NSPredicate predicateWithFormat:@"eventPlacesMale == %@ || eventPlacesMale != %@",@"in stock",@"0"];
}
else{
soldOutPredicate = [NSPredicate predicateWithFormat:@"eventPlacesFemale == %@ || eventPlacesFemale != %@",@"in stock",@"0"];
}
fullPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[soldOutPredicate]];
}
if (soldOutPredicate && criteriaMatchPredicate) {
fullPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[soldOutPredicate,criteriaMatchPredicate]];
}
if (fetchedObjects && fetchedObjects.count > 0) {
SDMFeaturedEvent *feat = [fetchedObjects objectAtIndex:0];
NSLog(@"All featured events %@",feat.featuredEvents);
if (fullPredicate) {
return [[feat.featuredEvents.allObjects filteredArrayUsingPredicate:fullPredicate]sortedArrayUsingDescriptors:@[usesDescriptor]];
}
else if (![[NSSDMUserDetails sharedManager]showsCriteraMatchEvents]){
return [feat.featuredEvents.allObjects sortedArrayUsingDescriptors:@[usesDescriptor]];
}
else{
return [NSArray new];
}
}
return [NSArray new];
The trick was to return an array of events from the featuredEvent "featuredEvents" property, you can then run the filteredArrayUsingPredicate and sortedArrayUsingDescriptor methods to sort the event objects in the array with whatever your requirements are. Granted this is not returning an NSFetchedResultsController but this works great for filtering.