I was trying to find a solution to this, but couldn’t find one. I ended up figuring it out myself, so I thought I’d share with any iPhone devs out there trying to implement a robust UITableView Search Bar.
Problem: Searching a long block of text from a short search term using an NSComparisonResult. Apple’s TableSearch example only provides an example that searches from an array of single term categories (“Countries”). I wanted to give users the option to search in a scope of single word “Names”, “Descriptions” (long blocks of text corresponding to Names) or Both.
This is an extension of Apple’s sample app “TableSearch”-
plistData is an NSDictionary whose Keys are Names (single word Strings) and whose Values are Descriptions (long blocks of text).
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
//Update filtered array based on the search text and scope
[self.filteredContent removeAllObjects]; //First clear the filtered array
for (NSString *string in allNames) {
//Search only the Names
if ([scope isEqualToString:@"Names"]) {
NSComparisonResult result = [string compare:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchText length])];
if (result == NSOrderedSame) {
[self.filteredContent addObject:string];
}
//Search only the descriptions
} else if ([scope isEqualToString:@"Descriptions"]) {
NSString *description = [plistData objectForKey:string];
NSComparisonResult result = [description compare:searchText
options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)
range:[description rangeOfString:searchText
options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)]];
if (result == NSOrderedSame) {
[self.filteredContent addObject:string];
}
//Search only the Names
} else if ([scope isEqualToString:@"All"]) {
NSString *description = [plistData objectForKey:string];
NSComparisonResult resultName = [string compare:searchText
options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)
range:NSMakeRange(0, [searchText length])];
NSComparisonResult resultDescription = [description compare:searchText
options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)
range:[description rangeOfString:searchText
options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)]];
if (resultDescription == NSOrderedSame || resultName == NSOrderedSame) {
[self.filteredContent addObject:string];
}
}
}
}
The important difference between searching Names and searching Descriptions is the “range” option of NSString’s “compare” function. When searching single Names, searching from a range of the beginning of the string (index 0) to the end of the searchText is appropriate because you are only searching from the beginning of Name strings. However, when searching a long block of text, you want to search from every word, not just the first word of the Description.
In order to do this, the range of the string compare must be be in the range of a nested search of the search terms. Search for the range, then search at the range.
There are probably a number of optimizations that can be done here- I welcome any Comments in doing so.








No Response to Searching a block of text in a UITableView Search Bar using NSComparisonResult
Still quiet here.