I have a set of users in CoreData and an search field in my application. User has the properties firstname and name.
Currently I have a predicate like \"user.name CO
I don't think that you can combine "IN" with "CONTAINS" in a predicate. But you could split the search string into words, and create a "compound predicate":
NSString *searchString = @"John Sm ";
NSArray *words = [searchString componentsSeparatedByString:@" "];
NSMutableArray *predicateList = [NSMutableArray array];
for (NSString *word in words) {
if ([word length] > 0) {
NSPredicate *pred = [NSPredicate predicateWithFormat:@"user.name CONTAINS[c] %@ OR user.firstname CONTAINS[c] %@", word, word];
[predicateList addObject:pred];
}
}
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicateList];
NSLog(@"%@", predicate);
This example produces the predicate
(user.name CONTAINS[c] "John" OR user.firstname CONTAINS[c] "John") AND
(user.name CONTAINS[c] "Sm" OR user.firstname CONTAINS[c] "Sm")
which would match "John Smith", but not "John Miller".
I had the same problem and solved it like this:
In my NSManagedObject class (user) I added the following method, merging the two values into a single string:
- (NSString *)name
{
return [NSString stringWithFormat:@"%@ %@", self.firstname, self.lastname];
}
Then you'll only need the following lines to match against your list, which is in my case an NSArray with user objects:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name contains[c] %@", searchString];
NSArray *filteredUsers = [users filteredArrayUsingPredicate:predicate];
Swift 4 Update:
let firstName = NSPredicate(format: "firstName CONTAINS[c] %@", searchText)
let lastName = NSPredicate(format: "lastName CONTAINS[c] %@", searchText)
let orCompoundPredicate = NSCompoundPredicate(orPredicateWithSubpredicates:
[firstNamePredicate,lastNamePredicate]
Use the orCompoundPredicate while fetching data.
2.5 years later I can answer my question with a bit more complex example in swift:
var predicateList = [NSPredicate]()
let words = filterText.componentsSeparatedByString(" ")
for word in words{
if count(word)==0{
continue
}
let firstNamePredicate = NSPredicate(format: "firstName contains[c] %@", word)
let lastNamePredicate = NSPredicate(format: "lastName contains[c] %@", word)
let departmentPredicate = NSPredicate(format: "department contains[c] %@", word)
let jobTitlePredicate = NSPredicate(format: "jobTitle contains[c] %@", word)
let orCompoundPredicate = NSCompoundPredicate(type: NSCompoundPredicateType.OrPredicateType, subpredicates: [firstNamePredicate, lastNamePredicate,departmentPredicate,jobTitlePredicate])
predicateList.append(orCompoundPredicate)
}
request.predicate = NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: predicateList)