When I push a view after a user has selected a UITableView row, the row gets a blue highlight, and then the new view appears. That's fine. But when I go 'back' the row is still highlighted in blue. Here's my didSelectRowAtIndexPath code.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
SettingsViewController *controller = [[SettingsViewController alloc] initWithNibName:@"SettingsView" bundle:nil];
[[self navigationController] pushViewController:controller animated:YES];
[controller release], controller = nil;
}
What am I doing wrong?
If your controller is based on
UITableViewController
, you get this feature for free. But I often ended up usingUIViewController
with no. of other controls in addition toUITableView
, in that case, you should override yourviewWillAppear
toAs the answers above point out, you need to explicitly deselect the row. You have two options as to how you do this. The first, is to deselect the row immediately after selection:
That will work just fine, but there is an alternative, and its the approach taken by
UITableViewController
which is to leave the row selected then deselect it when the view re-appears (after the controller you're pushing is popped off of the stack).This has the slight advantage that the user sees a glimpse of their previous selection when they return so they can see what they had selected previously.
To implement this, you just need to override
viewWillAppear
:As I said, this is what the default of implementation of
UITableViewController
'sviewWillAppear:
does so if you are usingUITableViewController
and not seeing this behaviour, you should check that you are calling thesuper
implementation in your class' ownviewDidAppear:
.Update (30 Oct 2013): well, this is a popular answer! As Ben rightly points out in the comments, UITableViewController actually does this in
viewWillAppear:
notviewDidAppear:
- this is the correct timing. In addition, you turn this behaviour on and off using theclearsSelectionOnViewWillAppear
property of UITableViewController. I've amended my answer above to reflect this.You just need to call [tableView deselectRowAtIndexPath: indexPath animated: YES].
UITableViewController
has a BOOL property calledclearsSelectionOnViewWillAppear
which does exactly what you want.By default it is set to
YES
, but I've noticed that you can (sometimes accidentally) disable this property by implementing your ownviewWillAppear:
method. I think this is because the deselection happens during[UITableViewController viewWillAppear:]
which might never get called if you override it.The solution is easy, then. Just call super's version of
viewWillAppear:
somewhere in your version of that method:Apple recommends always calling the super version of any of the view{Did,Will}{A,Disa}ppear methods if you override them.
References
Another solution is to call UITableView's reloadData in viewWillAppear
You need to deselect it:
[tableView deselectRowAtIndexPath:indexPath animated:YES];