Implement a search similar to that of native contacts?
In the native contacts app, when you try to find contacts, you enter some string and if the first and last name of the contact person / company, etc. start with this line, the contact will be displayed.
To make things more complicated, you can type something like Mi Ric and a search will find Michael Richardson. Also Rick Mee will get me Michael Richardson.
I made a copy of the contact entry in my local kernel datastore and now my first instinct is to use NSFetchedResultsController
some good predicate as well.
But how would I go about this predicate? If a person's entry has up to 3 words, should I query each word with beginWith? Can even one predicate do this?
source to share
This is what I use for the word base predicate:
+ (NSPredicate *)wordBasedPredicateForString:(NSString *)searchString withProperty:(NSString *)property
{
// searchString = [searchString stringForSearch];
NSArray *searchStrings = [searchString componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSMutableArray<NSPredicate *> *subPredicates = [NSMutableArray array];
for (NSString *string in searchStrings)
if (![string isEqualToString:@""]) {
NSString *mainString = [property stringByAppendingString:@" CONTAINS[cd] "];
mainString = [NSString stringWithFormat:@"%@ CONTAINS[cd] %%@",property];
NSPredicate *predicate = [NSPredicate predicateWithFormat:mainString, string];
[subPredicates addObject:predicate];
}
if ([searchString containsString:@" "] && subPredicates.count > 0) {
NSString *mainString = [property stringByAppendingString:@" CONTAINS[cd] "];
mainString = [mainString stringByAppendingString:@"' '"];
NSPredicate *emptySpacePredicate = [NSPredicate predicateWithFormat:mainString, nil];
[subPredicates addObject:emptySpacePredicate];
}
NSCompoundPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:subPredicates];
return predicate;
}
suppose we have an object Contact
with the propertyname
NSPredicate *namePredicate = [self wordBasedPredicateForString:searchString withProperty: @"name"];
then filter the array:
NSArray *results = [contacts filteredArrayUsingPredicate:namePredicate];
and of course you can do multiple word base predicates for name, company, address, etc. and create one compound file like this:
orPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[namePredicate, addressPredicate, phonePredicate]];
Hope this helps;)
source to share
You can also try this solution
Let's take the MyContact
class
class MyContact: NSManagedObject {
@NSManaged var contact_id: String // Primary key
@NSManaged var firstname: String
@NSManaged var lastname: String
var fullName: String {
return firstname + " " + lastname
}
}
You now have a string fullName
in your object. so you can easily run a predicate on it. it doesn't matter if yours searchString
matches your first or last name.
Now add your search logic: -
var currentContacts : [MyContact] = []
var contacts : [MyContact] = []
Your tableView delegate method, array currentContacts
and array used contacts
just hold all pins.
You can filter the array contacts
according to your search string.
currentContacts = contacts.filter { (element: MyContact) -> Bool in
return element.fullName.localizedCaseInsensitiveContainsString(searchString)
}
tableView.reloadData()
Hope this helps;)
source to share