lemontwist
lemontwist

Reputation: 301

How can I figure out what UITableViewCell I'm clicking on during a search?

I have a table view set up with a search bar. Everything works great: when I type text into the search bar, the results update in the table view based on my search text. The problem I'm having is in determining what the ID of the table cell is to pass that along when I'm going to my detail view. To clarify: the cells in the table view are usually generated from a SQLite3 database and ordered by their name. So if I have 4 cells: (Cabernet Cortis, Cabernet Franc, Cabernet Sauvignon and Ruby Cabernet), their IDs are normally (78, 79, 80, 378). However when I search "cabernet", and these four items come up, the indexPath.row is (1, 2, 3, 4) instead of (78, 79, 80, 378) so it's taking me to the wrong grape in the detail view (which are the first four grapes in alpha order as entered into my DB).

Here is some code to help clear things up. I think what would help is if I can obtain the ID of each grape that comes up as a search result and also have an MSMutableArray of those values, and then use [actualIDNumber objectAtIndex:indexPath.row] instead of just indexPath.row.

//ViewGrapesViewController.h
@property (strong, nonatomic) IBOutlet UISearchBar *searchBar;
- (void) searchGrapesTableView;
@property (nonatomic, retain) NSMutableArray *listOfGrapes;
@property (nonatomic, retain) NSMutableArray *searchResult;
@property (nonatomic, retain) NSMutableArray *searchResultID;
@property (nonatomic) Boolean isSearchOn;

//ViewGrapesViewController.m
//synthesize variables, etc
- (void)viewDidLoad
    {
        //obtain grapes from the DB, etc.
        //add searchNames to an NSMutableArray
        listOfGrapes = [[NSMutableArray alloc] init];
        for (int i=1; i<=[self.grapes count]; i++) {
            Grapes *theGrape = [self.grapes objectAtIndex:(i-1)];
            NSString *grapeSearchName = theGrape.searchName;
            [listOfGrapes addObject:grapeSearchName];
        }
        searchResult = [[NSMutableArray alloc] init];
        searchResultID = [[NSMutableArray alloc] init];
        isSearchOn = NO;

    //search bar stuff
    searchBar.autocorrectionType = UITextAutocorrectionTypeNo;

    [super viewDidLoad];
}

- (void) searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
    isSearchOn = YES;
}

- (void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
    if ([searchText length] > 0) {
        isSearchOn = YES;
        [self searchGrapesTableView];
    }
    else {
        isSearchOn = NO;
    }
    [self.tableView reloadData];
}

- (void) searchGrapesTableView {
    [searchResult removeAllObjects];
    [searchResultID removeAllObjects];
    for (NSString *str in listOfGrapes)
    {
        NSRange titleResultsRange = [str rangeOfString:searchBar.text options:NSCaseInsensitiveSearch];
        if (titleResultsRange.length > 0) {
            [searchResult addObject:str];
            //would love to add ID to searchResultID array here, don't know how to do that
        }
    }
}

- (void) searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    [self searchGrapesTableView];
}

- (void) searchBarTextDidEndEditing:(UISearchBar *)searchBar {
    isSearchOn = NO;
    [self.searchBar resignFirstResponder];
    [self.tableView reloadData];
}

//table view code
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    //first check if the user is searching
    if (isSearchOn) {
        return 1;
    }
    //if not, then search by alpha order
    else {
        return 24;
    }
}

//create header titles & number of rows in section (it's a lot of code and works fine)

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"grapeCell";
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    //is the user searching?
    if (isSearchOn) {
        NSString *cellValue = [searchResult objectAtIndex:indexPath.row];
        cell.textLabel.text = cellValue;
    }

    //otherwise...
    else {
        NSInteger theNumber;
        NSInteger numberToAdd = [[howManyRowsInSection objectAtIndex:indexPath.section] integerValue];
        theNumberToAdd = numberToAdd;
        theNumber = numberToAdd + indexPath.row;

        //cell title = grape name
        Grapes *grape = [self.grapes objectAtIndex:theNumber];
        NSString *theGrapeName = grape.grapeName;
        cell.textLabel.text = theGrapeName;
    }
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    //is the user searching?
    if (isSearchOn) {
        theNumberToAdd=0; //which is wrong but here for the time being
        //i have to have the ID here in order to do some logic to figure out what row to return
    }

    //otherwise...
    else {
        theNumberToAdd = [[howManyRowsInSection objectAtIndex:indexPath.section] integerValue]; // i performed this logic elsewhere
    }


    ViewGrapeViewController *detailViewController = (ViewGrapeViewController *)self.presentedViewController;
    detailViewController.detailItem = [self.grapes objectAtIndex: (indexPath.row+theNumberToAdd)];
}

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"toGrapeDetail"]) {       
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        //is the user searching
        if (isSearchOn) {
            theNumberToAdd=0;  // which is wrong
        }

        //otherwise...
        else {
            theNumberToAdd = [[howManyRowsInSection objectAtIndex:indexPath.section] integerValue];
        }

        NSDate *object = [_objects objectAtIndex:(indexPath.row+theNumberToAdd)];
        [[segue destinationViewController] setDetailItem:object];
    }
}

Upvotes: 2

Views: 248

Answers (2)

Ben Coffman
Ben Coffman

Reputation: 1740

You could also create a sequential tag number for each cell that correlates to your Array count. Then you grab the tag number and use it for the object at index.

This might be slightly more efficient than searching each string and it would accommodate for duplicate string names.

Code would be in:

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

 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SectionCellIdentifier];
 cell.tag = i //where i increments by one each entry into the function.
 }

Upvotes: 0

Dustin
Dustin

Reputation: 6803

In your did select item method, get the text from the cell that was selected and iterate through your array until you find an item that matches, then open that cell's detail view. This only will work if you have all unique item names.

- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *str = [[[tableView cellForRowAtIndexPath:indexPath] textLabel] text];
    for (int j=0; j<whateverArray.count; j++)
    {
        NSString *temp = [whateverArray objectAtIndex:j];
        if ([str isEqualToString:temp])
        {
            //do whatever you would do if the user actually clicked the row at position j
        }
    }
}

Upvotes: 1

Related Questions