I am trying to use a UISearchBar
to query multiple properties of a NSManagedObject
I have a NSManagedObject
called Person
To avoid the warning Incompatible pointer types initializing 'NSCompoundPredicate *_strong' with an expression of type 'NSPredicate *', replace the following:
NSCompoundPredicate * predicate = [NSCompoundPredicate orPredicateWithSubPredicates:subPredicates];
with this:
NSPredicate * predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];
Source: NSCompoundPredicate
This is may be useful if you want to search multiple properties for anything that matches (eg UISearchControllerDelegate):
NSString *searchFor = @"foo";
NSArray *fields = @[@"Surname", @"FirstName", @"AKA", @"Nickname"]; // OR'd dictionary fields to search
NSMutableArray *predicates = NSMutableArray.new;
for (NSString *field in fields) {
[predicates addObject:[NSPredicate predicateWithFormat:@"(%K BEGINSWITH[cd] %@)", field, searchFor]];
}
NSPredicate *search = [NSCompoundPredicate orPredicateWithSubpredicates:predicates];
You could then use this, for example, to filter an array of dictionaries:
NSArray *results = [bigArray filteredArrayUsingPredicate:search];
(the BEGINSWITH[cd] is no magic, just means it'll match beginnings of strings and case-insensitive. Change as needed for your match criteria.)
You could use a NSCompoundPredicate.
Like this:
NSPredicate *predicateName = [NSPredicate predicateWithFormat:@"name contains[cd] %@", query];
NSPredicate *predicateSSID = [NSPredicate predicateWithFormat:@"socialSecurity contains[cd] %@", query];
NSArray *subPredicates = [NSArray arrayWithObjects:predicateName, predicateSSID, nil];
NSPredicate *orPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];
request.predicate = orPredicate;
there is a NSCompoundPredicate
for AND
too: andPredicateWithSubpredicates:
For Swift:
var predicate = NSCompoundPredicate(
type: .AndPredicateType,
subpredicates: [predicate1, predicate2]
)
Fraser Hess over at CISMGF.com has a great search example. You can read the post at http://www.cimgf.com/2008/11/25/adding-itunes-style-search-to-your-core-data-application/
My code based off the post is:
NSArray *searchTerms = [searchText componentsSeparatedByString:@" "];
if ([searchTerms count] == 1) { // Search in name and description
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(name contains[cd] %@) OR (desc contains[cd] %@)", searchText, searchText];
[self.searchFetchedResultsController.fetchRequest setPredicate:predicate];
} else { // Search in name and description for multiple words
NSMutableArray *subPredicates = [[NSMutableArray alloc] init];
for (NSString *term in searchTerms) {
NSPredicate *pred = [NSPredicate predicateWithFormat:@"(name contains[cd] %@) OR (desc contains[cd] %@)", term, term];
[subPredicates addObject:pred];
}
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates];
[self.searchFetchedResultsController.fetchRequest setPredicate:predicate];
}
Addition to @Matthias's answer, you can also use NSCompoundPredicate for your AND operations like this.
Obj-C - AND
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"X == 1"];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"X == 2"];
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicate1, predicate2]];
Swift - AND
let predicate1:NSPredicate = NSPredicate(format: "X == 1")
let predicate2:NSPredicate = NSPredicate(format: "Y == 2")
let predicate:NSPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate1,predicate2] )
Swift 3 - AND
let predicate1 = NSPredicate(format: "X == 1")
let predicate2 = NSPredicate(format: "Y == 2")
let predicateCompound = NSCompoundPredicate(type: .and, subpredicates: [predicate1,predicate2])