I have a Person
Object which has two NSString
properties; firstName and lastName
.
I'm currently using an NSPredicate
like so:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(firstName contains[cd] %@) OR (lastName contains[cd] %@)", searchText, searchText];
So, for example, say I'm searching for the name "John Smith"
. In my search bar if I type "Joh"
, then John Smith
will appear as an option. This is good and fine, but if I type in "John Sm"
it will go blank.
How can I join firstName and lastName in the predicate
so if I was searching for "John Sm"
then John Smith
would still appear as an option.
I hope this makes sense. Thanks.
EDIT:
To add a bit more clarification, I'm using the SearchDisplayController
delegate method:
-(void)filterContentForSearchText:(NSString *)searchText scope:(NSString *)scope;
and I'm using the predicate
like so:
newArray = [personObjectArray filteredArrayUsingPredicate:predicate];
Try this,
NSString *text = @"John Smi";
NSString *searchText = [text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSArray *array = [searchText componentsSeparatedByString:@" "];
NSString *firstName = searchText;
NSString *lastName = searchText;
NSPredicate *predicate = nil;
if ([array count] > 1) {
firstName = array[0];
lastName = array[1];
predicate = [NSPredicate predicateWithFormat:@"(firstName CONTAINS[cd] %@ AND lastName CONTAINS[cd] %@) OR (firstName CONTAINS[cd] %@ AND lastName CONTAINS[cd] %@)", firstName, lastName, lastName, firstName];
} else {
predicate = [NSPredicate predicateWithFormat:@"firstName CONTAINS[cd] %@ OR lastName CONTAINS[cd] %@", firstName, lastName];
}
NSArray *filteredArray = [people filteredArrayUsingPredicate:predicate];
NSLog(@"%@", filteredArray);
Output:
(
{
firstName = John;
lastName = Smith;
}
)
Here text represents the searched text. The advantage with the above is, even if you pass text = @"Smi Joh";
or text = @"John ";
or text = @" smi";
or text = @"joh smi ";
, it will still show the above output.
The solution suggested above will not work with search strings that have more than two words. Here is a more thorough implementation in swift. This solution also allows for adding more fields on a record, if your goal is to implement a full text search across name, email, phone number, etc. In that case just update the NSPredicate to OR newField CONTAINS[cd] %@
and be sure to add the extra $0 in the list of string replacements.
let searchText = search.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
let words = searchText.componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceCharacterSet())
let predicates = words.map { NSPredicate(format: "firstName CONTAINS[cd] %@ OR lastName CONTAINS[cd] %@", $0,$0) }
let request = NSFetchRequest()
request.predicate = NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: predicates)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With