Illep
Illep

Reputation: 16841

Writing an NSPredicate

I have several problems relating to NSPredicates, here are they;

1.) My code is as follows;

 NSArray *arr= [self.humanArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"ANY name IN %@ ", nameArray]];

I get the following exception;

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'The left hand side for an ALL or ANY operator must be either an NSArray or an NSSet.'

*** Call stack at first throw:

When i write the predicate as @"name IN %@ ", nameArray. It works, but i think there might be some underneath flaw in this.

note: the humanArray, contains objects of HUMAN, and an object of human contains the following attributes. name, age, gender, country, region.

2.) I think what i am doing here, is wrong. The user is given the option to filter the self.humanArray. The user may filter using one, more or none of the following criteria;

name, age, gender, country or region.

My code looks like this;

 NSArray *fRegionArray= [self.humanArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"regionIN %@ ", regionArray]];



 NSArray *fCountryArray= [fRegionArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"country IN %@ ", countryArray]];



 NSArray *fNameArray= [fCountryArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"name IN %@ ", nameArray]];

This code works, if the user selects all the filter attributes (region, country and name). If you look at the above code you will notice that the output array of the 1st predicate is used for filtering in the 2nd predicate. So that is the reason for it to behave this way.

I need to modify the above code, so that the user would enter any of the attributes for filtering purposes. region or country or name.

Upvotes: 1

Views: 447

Answers (2)

Leonardo
Leonardo

Reputation: 9857

I did this in a project of mine Where I needed to filter an array of objects based on multiple criteria.  

NSPredicate *filterBlock = [NSPredicate predicateWithBlock: ^BOOL(id obj, NSDictionary *criteria){

        NSString *name = [criteria objectForKey:@"name"];
        NSString *gender =....................

        YourObject *yo = (YourObject*)obj;
        if (yo.name isEqualToString:name && yo.gender isEqualToString:gender) {
            // refine all your criteria
            return YES;
        } else {
            return NO;
        }
}];


NSArray *result = [arrayToBeFiltered filteredArrayUsingPredicate:filterBlock];

It worked, and it's not so bad concerning speed.

Upvotes: 1

Fjölnir
Fjölnir

Reputation: 490

  1. foo IN already means any object foo in said array. You'd use ANY followed by a basic expression (example ANY objects.value < 13). IN is an aggregate expression.
  2. You could use a temporary value and filter it only by attributes actually used?

Upvotes: 1

Related Questions