Question

I've been having trouble getting a search bar working within my iPhone app which is a drink dictionary. It works fine with the core data loading everything and when searching it filters perfectly, but when I select a drink after I have done a search, it always returns the first item in the list. I should mention that I am doing a hybrid of a fetchedResultsController and a normal fetch request depending on the drink type (in this instance, I used the fetched results controller when doing the big data pulls and the normal fetch request for user created data). Here is my relevant code:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = @"drink";
SWTableViewCell *cell = (SWTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
Drink *drinkCell;

    if ([self.currentDrinkType.name isEqualToString:@"Beer"] || [self.currentDrinkType.name isEqualToString:@"Wine"] || [self.currentDrinkType.name isEqualToString:@"Liquor"] ){
    drinkCell = [_fetchedResultsController objectAtIndexPath:indexPath];
    }else{
        if (tableView == self.searchDisplayController.searchResultsTableView){
            drinkCell = [_searchResults objectAtIndex:indexPath.row];
        }else{
        drinkCell = [_drinks objectAtIndex:indexPath.row];
        }

}
   //Check if cell object has already been favorited, if it has render unfavorite button instead
    NSMutableArray *rightUtilityButtons = [NSMutableArray new];
    NSString *favoriteText;
    if ([drinkCell.isFavorite boolValue]){
        favoriteText = @"Unfavorite";
    }else{
        favoriteText = @"Favorite";
    }
        [rightUtilityButtons sw_addUtilityButtonWithColor:
         [UIColor colorWithRed:0.78f green:0.78f blue:0.8f alpha:1.0]
                                                    title:favoriteText];


    //Can only delete a drink if it is custom
    if ([drinkCell.isCustom boolValue] && drinkCell.isCustom != nil){
    [rightUtilityButtons sw_addUtilityButtonWithColor:
     [UIColor colorWithRed:1.0f green:0.231f blue:0.188 alpha:1.0f]
                                                title:@"Delete"];

        [rightUtilityButtons sw_addUtilityButtonWithColor:
         [UIColor colorWithRed:0.231f green:0.231f blue:1.0f alpha:1.0f]
                                                    title:@"Edit"];

    }

    cell = [[SWTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
                                  reuseIdentifier:CellIdentifier
                              containingTableView:self.tableView // For row height and selection
                               leftUtilityButtons:nil
                              rightUtilityButtons:rightUtilityButtons];
    cell.delegate = self;


// Configure the cell...

[self configureCell:cell atIndexPath:indexPath tableView:tableView];

return cell;

}

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath tableView:(UITableView *)tableView {
Drink *drinkCell;
if ([self.currentDrinkType.name isEqualToString:@"Beer"] || [self.currentDrinkType.name isEqualToString:@"Wine"] || [self.currentDrinkType.name isEqualToString:@"Liquor"] ){
    drinkCell = [_fetchedResultsController objectAtIndexPath:indexPath];
}else{
    if (tableView == self.searchDisplayController.searchResultsTableView){

        drinkCell = [_searchResults objectAtIndex:indexPath.row];
    }else{
         drinkCell = [_drinks objectAtIndex:indexPath.row];
    }


}
cell.textLabel.text = drinkCell.name;
cell.detailTextLabel.text = [NSString stringWithFormat:@"%@%%", drinkCell.alcoholByVolume];

}

The search filtering code

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope{
NSPredicate *resultPredicate;

if ([self.currentDrinkType.name isEqualToString:@"Beer"] || [self.currentDrinkType.name isEqualToString:@"Wine"] || [self.currentDrinkType.name isEqualToString:@"Liquor"]){
    resultPredicate= [NSPredicate predicateWithFormat:@"SELF.name contains[cd] %@ AND drinkType ==%@",searchText, self.currentDrinkType];
    [NSFetchedResultsController deleteCacheWithName:[NSString stringWithFormat:@"Root%@", self.currentDrinkType]];
    [_fetchedResultsController.fetchRequest setPredicate:resultPredicate];

    NSError *error = nil;
    if (![[self fetchedResultsController] performFetch:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

}else{
    resultPredicate= [NSPredicate predicateWithFormat:@"SELF.name contains[cd] %@",searchText];
    _searchResults = [[_drinks filteredArrayUsingPredicate:resultPredicate]mutableCopy];
}

}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

//TODO handle drink selection
NSManagedObjectContext *context = [self managedObjectContext];
 Drink *theDrink;
NSLog(@"index path %d", indexPath.row);
NSLog(@"search index %d", self.searchDisplayController.searchResultsTableView.indexPathForSelectedRow.row);
NSManagedObject *selectedDrink;
if ([self.currentDrinkType.name isEqualToString:@"Beer"] || [self.currentDrinkType.name isEqualToString:@"Wine"] || [self.currentDrinkType.name isEqualToString:@"Liquor"] ){
            theDrink = [_fetchedResultsController objectAtIndexPath:indexPath];
    selectedDrink = [_fetchedResultsController objectAtIndexPath:indexPath];

}else{
    if (self.searchDisplayController.isActive){
        selectedDrink = [_searchResults objectAtIndex:indexPath.row];
        theDrink = [_searchResults objectAtIndex:indexPath.row];
    }else{
       selectedDrink = [_drinks objectAtIndex:indexPath.row];
        theDrink = [_drinks objectAtIndex:indexPath.row];
    }

}


[selectedDrink setValue:[NSDate date] forKey:@"lastChosen"];
NSError *error = nil;
// Save the object to persistent store
if (![context save:&error]) {
    NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]);

}

self.selectedDrink = theDrink;
[self.delegateDrink drinkTableViewControllerDidFinish:self];

[self dismissViewControllerAnimated:YES completion:^{

}];

}

This last method is the troubling one. It works perfectly fine when not in the search, but for some reason it does not recognize the index whenever the search is active. Thanks for any help.

edit: adding code for row count

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

if ([self.currentDrinkType.name isEqualToString:@"Beer"] || [self.currentDrinkType.name isEqualToString:@"Wine"] || [self.currentDrinkType.name isEqualToString:@"Liquor"] ){
    id  sectionInfo =
    [[_fetchedResultsController sections] objectAtIndex:section];
    return [sectionInfo numberOfObjects];
}else{
    if (tableView == self.searchDisplayController.searchResultsTableView){
        return [_searchResults count];
    }else{
        return [_drinks count];
    }
}

}

Was it helpful?

Solution

Solved this issue for anyone who stumbles on this. The issue was that I was initializing the SWTableViewCell with "self.tableView" instead of the "tableView" that was being passed in. Hence the UISearchTableView was not being passed in on selection messing everything up.

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