UITableView does not automatically deselect the selected row when the table re-appears
IphoneObjective CIosCocoa TouchUitableviewIphone Problem Overview
Normally a selected row in a UITableView
gets deselected with an animation when the user pops back from the detail view.
However, in my case where I have a UITableView
embedded in a UIViewController
I have to do it manually in viewWillAppear
like so:
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
// For some reason the tableview does not do it automatically
[self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow
animated:YES];
}
Why is this and how to fix it?
Iphone Solutions
Solution 1 - Iphone
When your main ViewController is from type UITableViewController, it has a property clearsSelectionOnViewWillAppear
, which is per default YES
- so it will clear the selection automatically.
This property is not available for an UITableView, i guess it's because it has no ViewWillAppear
method either.
A UIViewController doesn't need this property because it has no UITableView
originally.
conclusion: you'll have to implement it by yourself when you do not use a UITableViewController
.
Solution 2 - Iphone
Do the deselection in didSelectRowAtIndexPath
instead of viewWillAppear
:
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//show the second view..
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Solution 3 - Iphone
In swift, you can add the following lines in your viewWillAppear
if let indexPath = tableView.indexPathForSelectedRow() {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
In swift 2, it's without parantheses:
if let indexPath = tableView.indexPathForSelectedRow {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
In Swift 4 (and 3?) the function name was cleaned up:
if let indexPath = tableView.indexPathForSelectedRow {
tableView.deselectRow(at: indexPath, animated: true)
}
Solution 4 - Iphone
I dont think deselecting the selected row is automatic... I normally do it before pushing to the next view
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
// to do other things
[self.navigationController pushViewController:yourNextViewController animated:YES];
}
Solution 5 - Iphone
Nothing is wrong--deselecting the highlighted row is always "manual". If you look at Apple's sample code, you will see the same thing.
Solution 6 - Iphone
In Swift 3 / 4
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
Solution 7 - Iphone
If table view selections are not being cleared in a subclass of UITableViewController
, despite the fact that clearsSelectionOnViewWillAppear
is set to true, make sure to call the superclass version of [UIViewController viewWillAppear:animated]
if you override that method.
If you fail to call the super version of that method, the value of clearsSelectionOnViewWillAppear
will have no effect as the work of clearing the table view selection is actually performed in UITableViewController
's implementation of viewWillAppear
.
If your view controller does not inherit from UITableViewController
you will need to clear the selection manually in viewWillAppear
.
Solution 8 - Iphone
If you use UITableView without UITableViewController, you can check Apple's sample code Implementing Modern Collection Views - EmojiExplorerViewController.swift viewWillAppear
method for how to adopt animated deselection which is in-sync with view controller transition animation.
if let indexPath = self.collectionView.indexPathsForSelectedItems?.first {
if let coordinator = self.transitionCoordinator {
coordinator.animate(alongsideTransition: { context in
self.collectionView.deselectItem(at: indexPath, animated: true)
}) { (context) in
if context.isCancelled {
self.collectionView.selectItem(at: indexPath, animated: false, scrollPosition: [])
}
}
} else {
self.collectionView.deselectItem(at: indexPath, animated: animated)
}
}