Searching/Filtering a custom class array with a NSPredicate

I have a array that contains objects of a custom class, and I would like to filter the array based on if one of the classes attributes contains a custom string. I have a method that is passed the attribute that I want to be searched (column) and the string that it will search for (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 on
displayProviders = [[temp filteredArrayUsingPredicate:query] mutableCopy];
saying this class is not key value coding-compliant for the key [whatever searchString is].

  • How to search a UITableView
  • Real Time Search in UITableView
  • SearchBar not displaying results until cancel button clicked
  • IOS UISearchBar Background Color In iOS 9
  • Searching through an array of dictionaries
  • Xcode plist automatically jumps to the top after a search
  • Any ideas what I am doing wrong?

    3 Solutions Collect From Internet About “Searching/Filtering a custom class array with a NSPredicate”

    [NSPredicate predicateWithFormat:@"%@ contains %@", column,      searchString];
    

    When you use the %@ substitution in a predicate format string, the resulting expression will be a constant value. It sounds like you don’t want a constant value; rather, you want the name of an attribute to be interpreted as a key path.

    In other words, if you’re doing this:

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

    That is going to be the equivalent to:

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

    Which is the same as:

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

    That’s clearly not what you want. You want the equivalent of this:

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

    In order to get this, you can’t use %@ as the format specifier. You have to use %K instead. %K is a specifier unique to predicate format strings, and it means that the substituted string should be interpreted as a key path (i.e., name of a property), and not as a literal string.

    So your code should instead be:

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

    Using @"%K contains %K" doesn’t work either, because that’s the same as:

    [NSPredicate predicateWithFormat:@"name contains Dave"]
    

    Which is the same as:

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

    Replace %K to %@ in your predicate string,

    @"%@ contains %@", column, searchString
    

    This Works for me

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