Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSPredicate on an NSArray to search for any object

I have an array of objects with names, addresses, tel. nos, etc.

I want to be able to search the array for any occurrence of a term - whether in the name field, the address field, etc.

I have something like this in mind :

-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
    // Update the filtered array based on the search text and scope.
    // Remove all objects from the filtered search array


    [self.searchResults removeAllObjects];
    // Filter the array using NSPredicate
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[c] %@",searchText];
    searchResults = [NSMutableArray arrayWithArray:[contactArray filteredArrayUsingPredicate:predicate]];
}

This causes an exception "Can't use in/contains operator with collection".

UPDATE. I can now search on up to three fields. When I add a fourth (in any sequence), I get this exception: "Unable to parse the format string ..."

The Predicate code is now:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.narrative contains[c] %@ OR SELF.category contains[c] %@ OR SELF.date contains[c] OR SELF.name contains[c] %@", searchText, searchText, searchText, searchText];

     searchResults = [NSMutableArray arrayWithArray:[allDreams filteredArrayUsingPredicate:predicate]];

Is three a limit of predicate search fields? How do I get around this? Thanks again.

like image 877
ICL1901 Avatar asked Sep 16 '13 07:09

ICL1901


People also ask

What is NSArray Objective-C?

An object representing a static ordered collection, for use instead of an Array constant in cases that require reference semantics.

Can NSArray contain nil?

arrays can't contain nil. There is a special object, NSNull ( [NSNull null] ), that serves as a placeholder for nil.

Is NSArray ordered?

In Objective-C, arrays take the form of the NSArray class. An NSArray represents an ordered collection of objects. This distinction of being an ordered collection is what makes NSArray the go-to class that it is.


2 Answers

Just use a predicate string that checks for them all:

@"name contains[cd] %@ OR address contains[cd] %@"

you can add as many as you want.

The only downside is that you'll need to add the same search string for each field you want to test, which can seem a bit ugly.

If your objects are dictionaries, then there is a way to truly search all values without necessarily knowing their names at compile time, using a subquery.

It works like this:

@"subquery(self.@allValues, $av, $av contains %@).@count > 0"

It uses the @allValues special key (or method call if you prefer) for dictionary objects and uses that to filter any value that contains your search string. If any is found (i.e., the count is positive), the object is included in the results.

Notice that this will examine all values indiscriminately, even those that you don't want to include if you have any in your dictionary.

like image 66
Monolo Avatar answered Nov 07 '22 23:11

Monolo


I think your array item is not pure string, right?

Suppose your array item contains name attribute (even it's a dictionary), you can search it in this way:

NSPredicate * predicate =
  [NSPredicate predicateWithFormat:@"name CONTAINS[cd] %@ OR name LIKE[cd] %@", searchText, searchText];

here, name can be SELF.name.


HERE's an official document.

like image 4
Kjuly Avatar answered Nov 07 '22 22:11

Kjuly