Combining 'AND' and 'OR' Condition in NSPredicate

core-data, ios, nspredicate

Solution

I'll do the following using a `SUBQUERY`.

[NSPredicate predicateWithFormat@"(name == %@) AND (SUBQUERY(subs, $x, $x.numbervalue == %@ or $x.numbervalue == %@).@count > 0)", @"aname", value1, value2];

Try it and let me know.

Another solution could be to grab the whole collection `subs` and then filter the retrieved set with a predicate to check if elements match for `value1` or `value2`.

Hope it helps.

Edit

If you follow Eimantas suggestion make to sure to create the right array:

NSNumber valueA = [NSNumber numberWithInt:20];
NSNumber valueB = [NSNumber numberWithInt:90];
NSArray *arr = [NSArray arrayWithObjects:valueA, valueB, nil];

Problem

Back again needing more help with constructing my NSPredicates :( ``` Category { name:string subs<-->>SubCategory } SubCategory { name:string numbervalue:NSNumber } ``` I would like to know how to create a predicate with AND and OR. For example, I would like to return every Category with name == "category_name" that also has a subcategory with a numbervalue of "valueA" OR "valueB". I've tried every possible combination of predicate constructors I could come up with but I just cant get it to work. This is my best attempt so far. ``` NSPredicate *predicate=[NSPredicate predicateWithFormat@"(name== %@) AND (ANY subs.numbervalue==%@ OR ANY subs.numbervalue==%@)", @"aname", value1, value2]; ``` Edit 1 Second attempt. The filtering on the 'numbervalue' is still not working. ``` NSNumber valueA=[NSNumber numberWithInt:20]; NSNumber valueA=[NSNumber numberWithInt:90]; NSArray *arr=[NSArray arrayWithObject:valueA,valueB,nil]; predicate=[NSPredicate predicateWithFormat:@"(name==%@)AND(ANY subs.numbervalue IN %@)",@"aname",arr]; ``` Edit 2 I've tried filtering just by numberValue and have left the name out alltogether. 1) using this results in the entire set being returned even if only 1 item in the set has the value. ``` predicate=[NSPredicate predicateWithFormat:@"(ANY subs.numbervalue IN %@)",arr]; ``` 2) Using this results in the same problem, every item in the set being returned even if only 1 of them matches. ``` predicate=[NSPredicate predicateWithFormat:@"((SUBQUERY(subs, $x, $x.numbervalue == %@ or $x.numbervalue == %@).@count > 0)", value1, value2]; ``` Also using the simplest version results in the same problem.... I didnt notice this earlier. ``` NSPredicate *predicate=[NSPredicate predicateWithFormat@"(ANY subs.numbervalue==%@ ,valueA]; ``` So I think I have my problem narrowed down. Category is an Entity. SubCategory is an Entity. Category has a one to many relationship with SubCategory and is represented as an NSSet of SubCategory. Each SubCategory has an attribute named numbervalue. Edit 3 To test I have 2 Categorys. Both Categories have 10 subs, each with a numbervalue of 1 -10; Using this code both categories are returned along with all 10 subs for each. Expected result is both categories returned , each with just 2 subs. I've traced out all my objects and the data is correct. The problem is I cant return a category that has filtered subs. ``` NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSManagedObjectContext *context=[[DataSource sharedDataSource]managedObjectContext]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Category" inManagedObjectContext:context]; [fetchRequest setEntity:entity]; [fetchRequest setFetchBatchSize:20]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]; NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil]; NSPredicate *predicate; NSNumber *a=[NSNumber numberWithFloat:1]; NSNumber *b=[NSNumber numberWithFloat:2]; predicate=[NSPredicate predicateWithFormat:@"(SUBQUERY(subs,$x,$x.numbervalue==%@ or $x.numbervalue==%@).@count> 0)",a,b]; [fetchRequest setPredicate:predicate]; [fetchRequest setSortDescriptors:sortDescriptors]; NSError *error = nil; [NSFetchedResultsContoller deleteCacheWithName:nil]; NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:@"name" cacheName:@"Master"]; aFetchedResultsController.delegate = self; self.fetchedResultsController = aFetchedResultsController; if (![self.fetchedResultsController performFetch:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } ```

Original source