iPhone UITableView cells stay selected

in my UITableView sometimes cells stay selected after touching. Because it happens only occasionally, I'm not able to reproduce the problem.

Any hints? Maybe it has something to do with unproper releasing of tableView?

    - (void)tableView:(UITableView *)tableView 
    didSelectRowAtIndexPath:(NSIndexPath *)indexPath{   
    NSUInteger row = [indexPath row];

    [tableView deselectRowAtIndexPath:indexPath animated:YES];

switch (row) {
    case 0:
        FruitViewController *fruitController = [FruitViewController alloc];
        [fruitController retain];
        [fruitController initWithNibName:@"FruitView" bundle:[NSBundle mainBundle]];
        [self.navigationController pushViewController:fruitController animated:YES];
        [fruitController release];
        break;
    case 1: 
        CerealsViewController *cerealsController = [CerealsViewController alloc];
        [cerealsController retain];
        [cerealsController initWithNibName:@"CerealsView" bundle:[NSBundle mainBundle]];
        [self.navigationController pushViewController:cerealsController animated:YES];
        [cerealsController release];
        break;
    default:
        break;   
}
   }

Solution 1:

I can't tell you why you're seeing the issue, but here are some suggestions for fixing it:

According to the Apple HIG, the selection should not disappear until returning from the view controller just pushed onto the stack. If your controller is just a UITableViewController, it should deselect automatically upon returning to the view. If not, add

- (void) viewWillAppear:(BOOL)animated {
    [tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:animated];
    [super viewWillAppear:animated];
}

somewhere in the view controller.

If there are any rows that, when clicked, do not go to another view, and don't in fact do anything when selected, they shouldn't be selectable, so you can override that in

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath

and return nil in the cases that the row should not be selected.

Solution 2:

One possible cause is overriding -viewWillAppear:animated: without calling [super viewWillAppear] in a controller that extends UITableViewController. Adding [super viewWillAppear:animated] at the beginning of your -viewWillAppear method may rectify the problem.

Solution 3:

Just to expand on "Ed Marty"s answer, I chose to add the deselect in the "viewWillDisappear" method instead because I thought that it looked nicer.

In addition to this I was using a UITableView with a regular UIViewController (rather than a UITableViewController) so the tableView variable wasn't available to me. To overcome this I added a tableView property in my view controllers header file (and in my XIB file I connected the actual table view to the property)...

@property (nonatomic,retain) IBOutlet UITableView *tableView

...and in the view controllers implementation wired up the property and performed the deselect as follows..

@synthesize tableView

- (void) viewWillDisappear:(BOOL)animated {
    [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:animated];
    [super viewWillDisappear:animated];
}

Solution 4:

If you are using a UITableViewController you can use:

self.clearsSelectionOnViewWillAppear = YES;

Solution 5:

In my case , i deselect the cell right at the end of didSelectRowAtIndexPath :

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

    // Do smth here. segue ..etc

    [tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:NO];
}