Question

I have implemented a SearchBar using a UISearchDisplayController and a UITableView to display the search results in. I am using libxml2 and xpath to parse an HTML website and search the content needed in the source code. Since I am new to ObjC, I have used the sample project TableSearch provided by Apple for the searching and displaying part as a start. Everything works fine with this, I can parse specific contents from a website, and combine them correctly as they appear on the website and have them displayed in the different TableView rows' views. I want to use the user input to search a specific website for it. I only have the following problem:

If you take a look at the project TableSearch (class MainViewController.m), you will notice that it updates the "filteredListContent" and reloads the TableView displaying it automatically as the user types:

[...]

#pragma mark -
#pragma mark Content Filtering

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
 /*
  Update the filtered array based on the search text and scope.
  */

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

 /*
  Search the main list for products whose type matches the scope (if selected) and whose name matches searchText; add items that match to the filtered array.
  */
 for (Product *product in listContent)
 {
  if ([scope isEqualToString:@"All"] || [product.type isEqualToString:scope])
  {
   NSComparisonResult result = [product.name compare:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchText length])];
            if (result == NSOrderedSame)
   {
    [self.filteredListContent addObject:product];
            }
  }
 }
}


#pragma mark -
#pragma mark UISearchDisplayController Delegate Methods

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
    [self filterContentForSearchText:searchString scope:
   [[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];

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


- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
    [self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:
   [[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];

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


@end

You can imagine that it requires some memory when I use my implementation for parsing and searching and it is especially critical when it is called repeatedly while the user is typing in order to display "live results". When I only use the first line of my block for parsing and searching (initializing an NSData object with a URL) the SearchBar starts lagging and is delayed for a few seconds after each character typed. When I use the whole block, the app crashes. My question is the following:

How is it possible to wait for the "Search" or "Return" button on the keyboard to be tapped before a search is performed or where and how can I check whether the button was tapped? Sorry for this possibly trivial question.

Was it helpful?

Solution

Make your delegate object also the delegate of the search bar, and implement these methods as follows:

- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    [self filterContentForSearchText:[self.searchDisplayController.searchBar text]
                               scope:[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
    return NO;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
    return NO;
}

This will prevent the table view from reloading as the user types or changes scope, and reloads when the search button is clicked. However, the table does reload when the first character is entered. I have not yet found a way to prevent this action. As it is, the table will probably say no results when the first character is entered.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top