views:

111

answers:

2

In one of the code examples from Apple, they give an example of searching:

for (Person *person in personsOfInterest)
{
 NSComparisonResult nameResult = [person.name compare:searchText
            options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)
            range:NSMakeRange(0, [searchText length])];

 if (nameResult == NSOrderedSame)
 {
  [self.filteredListContent addObject:person];
 }
}

Unfortunately, this search will only match the text at the start. If you search for "John", it will match "John Smith" and "Johnny Rotten" but not "Peach John" or "The John".

Is there any way to change it so it finds the search text anywhere in the name? Thanks.

+5  A: 

Try using rangeOfString:options: instead:

for (Person *person in personsOfInterest) {
    NSRange r = [person.name rangeOfString:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)];

    if (r.location != NSNotFound)
    {
            [self.filteredListContent addObject:person];
    }
}

Another way you could accomplish this is by using an NSPredicate:

NSPredicate *namePredicate = [NSPredicate predicateWithFormat:@"name CONTAINS[cd] %@", searchText];
//the c and d options are for case and diacritic insensitivity
//now you have to do some dancing, because it looks like self.filteredListContent is an NSMutableArray:
self.filteredListContent = [[[personsOfInterest filteredArrayUsingPredicate:namePredicate] mutableCopy] autorelease];


//OR YOU CAN DO THIS:
[self.filteredListContent addObjectsFromArray:[personsOfInterest filteredArrayUsingPredicate:namePredicate]];
Dave DeLong
thumbs up on using NSPredicate.
pxl
Works perfectly, thanks. I ended up using the `rangeOfString:options` since I'm comparing to several fields (person.firstName, person.lastName).
nevan
@nevan you can put multiple comparisons inside a predicate; it's pretty much equivalent to a sql WHERE clause: `[NSPredicate predicateWithFormat:@"name CONTAINS[cd] %@ OR lastName CONTAINS[cd] %@", searchText, searchText];`
Dave DeLong
+1  A: 

-[NSString rangeOfString:options:] and friends are what you want. It returns:

"An NSRange structure giving the location and length in the receiver of the first occurrence of aString, modulo the options in mask. Returns {NSNotFound, 0} if aString is not found or is empty (@"")."

Quinn Taylor