Search code examples
subquerynspredicate

Is a subquery needed for my nspredicate to work properly?


I have an array of custom objects that have beds (1,2,3), fireplace (yes or no), den (yes or no) and ceiling heights (9-11,11-14,14-16). I need to allow filtering based on any/all/none of the items being selected to filter by. So a user may want to see 1 & 2 beds, den, fireplace and 9-11 foot ceilings. Or just 1 & 2 beds. My current predicate works for some of these. But it doesn't match all - only some. I am thinking I need a subquery. How to create a nested(?) subquery based on an array of filters?

Right now, the user selects buttons and those are matched against Filters and I use those to create my predicate.

Current predicate

    Filters is an array of keys and predicate strings like 'beds, 1' and 'ceilings, 9-11'

`NSMutableArray *subPredicates = [NSMutableArray array];

    for (Filter*fil in filters) {
        NSPredicate *unitsPredicate = [NSPredicate predicateWithFormat:@"%K == %@", fil.key, fil.predicate];
        [subPredicates addObject:bedsPredicate];
    }

    NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates];    
    NSLog(@"homes: %@", [searchArray filteredArrayUsingPredicate:predicate]);
    NSArray *ar = [searchArray filteredArrayUsingPredicate:predicate];

I'd like to allow someone to pick any of the criteria and return appropriate data.


Solution

  • Subqueries are used with to-many relationships. If you want to filter multiple values then the class of fil.predicate should be an array (or set) of values. The predicate format is %K IN %@, for example

    for (Filter*fil in filters) {
        NSPredicate *unitsPredicate;
        if ([fil.predicate isKindOfClass:[NSArray class]])
            unitsPredicate = [NSPredicate predicateWithFormat:@"%K IN %@", fil.key, fil.predicate];
        else
            unitsPredicate = [NSPredicate predicateWithFormat:@"%K == %@", fil.key, fil.predicate];
        [subPredicates addObject:bedsPredicate];
    }
    NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates];    
    

    See Aggregate Operations in Predicate Programming Guide.