views:

90

answers:

2

I'm sort of new to any sort of multithreading and simply can't seem to get a simple search method working on a background thread properly. Everything seems to be in order with an NSAutoreleasePool and the UI being updated on the main thread. The app doesn't crash and does perform a search in the background but the search results yield the several of the same items several times depending on how fast I type it in. The search works properly without the multithreading (which is commented out), but is very slow because of the large amounts of data I am working with. Here's the code:

    - (void)filterContentForSearchText:(NSString*)searchText { 
isSearching = YES;
 NSAutoreleasePool *apool = [[NSAutoreleasePool alloc] init];

 /*
  Update the filtered array based on the search text and scope.
  */

 //[self.filteredListContent removeAllObjects]; // First clear the filtered array.


 for (Entry *entry in appDelegate.entries)
 {
   NSComparisonResult result = [entry.gurmukhiEntry compare:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchText length])];
   if (result == NSOrderedSame)
   {
    [self.filteredListContent addObject:entry];
   }
 }

 [self.searchDisplayController.searchResultsTableView performSelectorOnMainThread:(@selector(reloadData)) withObject:nil waitUntilDone:NO];
 //[self.searchDisplayController.searchResultsTableView reloadData];

 [apool drain];
 isSearching = NO; }

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
     if (!isSearching) {
      [self.filteredListContent removeAllObjects]; // First clear the filtered array.
      [self performSelectorInBackground:(@selector(filterContentForSearchText:)) withObject:searchString];
     }
     //[self filterContentForSearchText:searchString];

        return NO;      // Return YES to cause the search result table view to be reloaded.  }
A: 

Several things:

  • Multithreading shouldn't bring any performance gains on a single core cpu. If you think you see great speedups, probably your algorithm is fishy.
  • If you access a shared variable, be sure it is thread safe. It seems like you are writing your search results into one shared object. This will fail without synchronization.
  • That code looks as if all threads work on exactly the same dataset, so if one thread finds a match, the others will find the same and put it also in there.
  • Don't forget to synchronize the access to your "results object" as well when accessing it from the main thread.
Eiko
A: 

You may want to look into NSOperation. Consider making a subclass of NSOperation and adding one as a property of the class implemented in the file you posted.

then in - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {

you can set the object with a pointer to the search data and text. Then you can check if the object is currently running (I think) and if so, call 'cancel' on it and start it over again with the new search string. There may be a smarter way, but I would suspect NSOperation is a good place to start looking.

Tom