Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple NSPredicate

I'm trying to prepare multiple search in my CoreData entity Recipes. There are parameters by which I would like to prepare fetch.

Recipes attributes:

@property (nonatomic, retain) NSNumber * difficulty;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSNumber * code; //like identifier
@property (nonatomic, retain) NSNumber * prepTime;

Ingredients is a separate entity with the list of ingredients.

Join entity contains ingredientCode, recipeCode, count.

getArrayOfJoinDataWithIngredients fetches join entity and returns NSArray of codes of recipes which contains some of input ingredient.

Here is my code:

- (IBAction)callRecipeFetch:(id)sender
{
    NSString *predicateString = @"";

    NSArray *codes = [[NSArray alloc] init]; codes = nil;
    if ([paramController.ingredientsForSearchArray count] > 0) {
        NSMutableArray *ingredientsArray = [[NSMutableArray alloc] init];
        for (Ingredients *ingredient in paramController.ingredientsForSearchArray) {
            [ingredientsArray addObject:ingredient.code];
        }
        MainTabController *mainTabController = [[MainTabController alloc] init];
        codes = [mainTabController getArrayOfJoinDataWithIngredients:ingredientsArray];

        NSString *ingrSet = [NSString stringWithFormat:@"(code IN %@)", codes];
        predicateString = [predicateString stringByAppendingString:ingrSet];
    }

    NSString *diff;
    if ([predicateString isEqualToString:@""]) {
        diff = [NSString stringWithFormat:@"(difficulty <= %d)", paramController.diff.selectedSegmentIndex + 1];
    }
    else diff = [NSString stringWithFormat:@" AND (difficulty <= %d)", paramController.diff.selectedSegmentIndex + 1];
    predicateString = [predicateString stringByAppendingString:diff];

    NSString *timeString = [NSString stringWithFormat:@" AND (%d =< prepTime) AND (prepTime <= %d)", paramController.rangeSlider.leftValue, paramController.rangeSlider.rightValue];
    predicateString = [predicateString stringByAppendingString:timeString];

    if (paramController.categoryCode) {
        NSString *categoryString = [NSString stringWithFormat:@" AND (inCategory = %@)", paramController.categoryCode];
        predicateString = [predicateString stringByAppendingString:categoryString];
    }

    NSPredicate *predicate = [NSPredicate predicateWithFormat: predicateString];
    [resultController findRecipesWithPredicate:predicate];
}

The full predicateString is @"(code IN (\n 1,\n 3\n)) AND (difficulty <= 5) AND (0 =< prepTime) AND (prepTime <= 28800) AND (inCategory = 12)"

Now I have an error in predicate part (code IN %@) when I prepare NSPredicate with code:

NSPredicate *predicate = [NSPredicate predicateWithFormat: predicateString];

ERROR:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unable     to parse the format string "(code IN (
1,
3
)) AND (difficulty <= 5) AND (0 =< prepTime) AND (prepTime <= 28800) AND (inCategory =  12)"'

How to correctly make predicate with IN operator. Thanks for all advices.

like image 991
Romowski Avatar asked May 20 '13 05:05

Romowski


2 Answers

use NSCompoundPredicate for your multiple predicates, you can refer NSCompoundPredicate Class Reference

something like this:

NSPredicate * andPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:predicate1,predicate2,predicate3,nil]];
like image 98
Joshua Avatar answered Oct 13 '22 01:10

Joshua


Addition to @Joshua's answer, you can also use NSCompoundPredicate for your OR operations like this.

Obj-C - OR

// OR Condition //

NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"X == 1"];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"X == 2"];
NSPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[predicate1, predicate2]];

Swift - OR

let predicate1:NSPredicate = NSPredicate(format: "X == 1")
let predicate2:NSPredicate = NSPredicate(format: "Y == 2")
let predicate:NSPredicate  = NSCompoundPredicate(orPredicateWithSubpredicates: [predicate1,predicate2] )

Swift 3 - OR

    let predicate1 = NSPredicate(format: "X == 1")
    let predicate2 = NSPredicate(format: "Y == 2")
    let predicateCompound = NSCompoundPredicate.init(type: .or, subpredicates: [predicate1,predicate2])
like image 43
Onur Var Avatar answered Oct 12 '22 23:10

Onur Var