UITableView does not automatically deselect the selected row when the table re-appears

IphoneObjective CIosCocoa TouchUitableview

Iphone 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)
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBesiView Question on Stackoverflow
Solution 1 - IphoneHermView Answer on Stackoverflow
Solution 2 - IphonejanusfidelView Answer on Stackoverflow
Solution 3 - IphoneKevin RView Answer on Stackoverflow
Solution 4 - IphoneNeoView Answer on Stackoverflow
Solution 5 - IphonenielsbotView Answer on Stackoverflow
Solution 6 - Iphoneoscar castellonView Answer on Stackoverflow
Solution 7 - IphoneScott AhtenView Answer on Stackoverflow
Solution 8 - IphonebillibalaView Answer on Stackoverflow