Finding / filtering a custom array of classes using NSPredicate

I have an array that contains custom class objects, and I would like to filter the array based on if one of the class attributes contains a custom string. I have a method that is passed the attribute that I want to search (column), and the string that it will search (searchString). Here is the code I have:

NSPredicate *query = [NSPredicate predicateWithFormat:@"%K contains %K", column, searchString]; NSMutableArray *temp = [displayProviders mutableCopy]; [displayProviders release]; displayProviders = [[temp filteredArrayUsingPredicate:query] mutableCopy]; [temp release]; 

However, it always throws an exception in displayProviders = [[temp filterArrayUsingPredicate: query] mutableCopy]; saying that this class is not a key value compatible with the encoding for the key [regardless of searchString].

Any ideas what I'm doing wrong?

+6
source share
3 answers
 [NSPredicate predicateWithFormat:@"%@ contains %@", column, searchString]; 

When you use the %@ substitution in the predicate format string, the resulting expression will be a constant value . It seems you do not want a constant value; rather, you want the attribute name to be interpreted as the key path.

In other words, if you do this:

 NSString *column = @"name"; NSString *searchString = @"Dave"; NSPredicate *p = [NSPredicate predicateWithFormat:@"%@ contains %@", column, searchString]; 

This will be equivalent to:

 p = [NSPredicate predicateWithFormat:@"'name' contains 'Dave'"]; 

This is the same as:

 BOOL contains = [@"name rangeOfString:@"Dave"].location != NSNotFound; // "contains" will ALWAYS be false // since the string "name" does not contain "Dave" 

This is clearly not what you want. You want the equivalent of this:

 p = [NSPredicate predicateWithFormat:@"name contains 'Dave'"]; 

To get this, you cannot use %@ as a format specifier. You should use %K instead. %K is a specifier unique to predicate format strings, and this means that the replaced string should be interpreted as the key path (that is, the name of the property), and not as a literal string.

So your code should be:

 NSPredicate *query = [NSPredicate predicateWithFormat:@"%K contains %@", column, searchString]; 

Using @"%K contains %K" does not work either, because it is the same as:

 [NSPredicate predicateWithFormat:@"name contains Dave"] 

This is the same as:

 BOOL contains = [[object name] rangeOfString:[object Dave]].location != NSNotFound; 
+19
source

Replace %K with %@ in your predicate string,

 @"%@ contains %@", column, searchString 
+1
source

It works for me

 [self.array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"name contains 'Dave'"]]; 
0
source

Source: https://habr.com/ru/post/895980/