iosuitableviewuisearchbar

UISearchBar calls API everytime a letter is typed and not on Searchbutton click


I'm working on a student project.

At this point our application can call the API and reload the data, but only if I call the XMLParser inside textDidChange.

Meaning: It calls and reloads correctly every time a letter is typed in UISearchBar. I Want the call and reload to only happen when the user clicks on the Search button, but the same code that works in textDidChange doesn't work in searchBarSearchButtonClicked.

Instead.. The method calls the API only when the searchbutton is pressed (good), receives the the same information like with textDidChange (good) but doesn't reload the UITableView (bad).

I have searched all over Stack Overflow for the answer to my problem, so I thought I'd post a question instead:)

All of the examples that I've come across only shows how to display the content of an array that matches the users criteria when the user types (contactlist), but doesn't show how to use the searchbutton to reload the UITableView correctly.

Why does the same exact code reload correctly in the delegate method

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText

but not in

- (void)searchBarSearchButtonClicked:(UISearchBar *)theSearchBar?

As I said, NSLog prints out the correct data to load the UITableview when the searchButton is clicked, so that is not the problem.

Can anyone point me in the right direction here? :)

My cellForRowAtIndexPath:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *uniqueIdentifier = @"searchCell";
    
    SearchCell *cell = nil;
    
    cell = (SearchCell *) [self.tableView dequeueReusableCellWithIdentifier:uniqueIdentifier];

    if(!cell)
    {
        NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"SearchCell" owner:nil options:nil];
        
        for (id currentObject in topLevelObjects) {
            if ([currentObject isKindOfClass:[SearchCell class]]) {
                cell = (SearchCell *)currentObject;
                break;
            }
        }
    }
    
    Search *currentSearch = [[searchxmlParser searchhits] objectAtIndex:indexPath.row];
    
    cell.track_label.text = [currentSearch track];
    cell.artist_label.text = [currentSearch artist];
    
    return cell;
}

The requested delegate methods:

- (void)searchBar:(UISearchBar *)theSearchBar textDidChange:(NSString *)searchText {
    
    NSString *searchurl = [NSString stringWithFormat:@"http://ws.spotify.com/search/1/track?q=%@", [self urlEncodeValue:searchText]];
    
    xmlParser = [[SearchXMLParser alloc] loadXMLByURL:searchurl];
    
    [self.tableView reloadData];
}

- (void)searchBarSearchButtonClicked:(UISearchBar *)theSearchBar {
    
    NSString *searchurl = [NSString stringWithFormat:@"http://ws.spotify.com/search/1/track?q=%@", [self urlEncodeValue:theSearchBar.text]];

    xmlParser = [[SearchXMLParser alloc] loadXMLByURL:searchurl];

    [self.tableView reloadData];

    [theSearchBar setShowsCancelButton:NO animated:YES];
    [theSearchBar resignFirstResponder];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.
    return 1;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    return [[searchxmlParser searchhits] count];
}

Solution

  • You should use an UISearchDisplayController.

    In your h file you should have declared 2 arrays one with the original dataSource and one with filtredValues. Alloc them in viewDidLoad and release in dealloc.

    In cellForRowAtIndexPat and in umberOfRowsInSection you should test witch tableView is displayed and return desired values.

    if(tableView == self.searchDisplayController.searchResultsTableView){
    // search view population
    } else {
    // all data view population
    }
    

    And with this approach you can use live search by filtring dataSource array and put the values in filtredArray.