UISearchDisplayController and Search Performance with Lots of Data
I am trying to find the best way to do a quick search using UISearchDisplayController
.
I have a plist file with over 36,000 records. I load this file into a dictionary and I search that dictionary. It works, but it is slow and there is a lag between each touch event. I want an autocomplete effect, so I need the search to fire for every touch event.
I tried to use thread to do a search in the background with the following code:
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[NSThread detachNewThreadSelector:@selector(filter:) toTarget:self withObject:searchString];
return NO;
}
// Filter function looks like this
-(void) filter:(NSString *)search {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[self.filteredList removeAllObjects]; // empty array of results
for (NSString *s in self.keys ) {
NSComparisonResult result = [s compare:search options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [search length])];
if (result == NSOrderedSame) {
[self. filteredList addObject:s ];
}
}
[ self.searchDisplayController.searchResultsTableView reloadData];
[pool release];
}
But my application crashes with the following message:
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index (1) beyond bounds (0).
I'm pretty sure because I am not using threading correctly.
I also tried to use [self performSelector:@selector(filter:) withObject:searchString afterDelay:0.5];
, but I also ran into application crashes.
What's the best way to handle this? I'm not very good at streaming, but I think this is the best way to go, right? I also tried the solution with SQLite, but the application is still not that responsive.
My details are postal codes and cities (36000 unique cities, but 6500 unique postal codes as multiple cities can have the same postcode). I want my search item to be either postcode or city name. I know that one big dictionary is definitely not the best structure. How can I organize my data for better performance?
Thanks for helping me with this.
source to share
The problem is that your search string is longer than one of your original strings in the array. When comparing 0 to [search length], you fall outside of s. You must first make sure s is longer than the search:
for (NSString *s in self.keys ) {
if ([s length]>=[search length]) {
NSComparisonResult result = [s compare:search options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [search length])];
if (result == NSOrderedSame) {
[self. filteredList addObject:s ];
}
}
}
source to share