3

I am using the following code to deselect a selected table view cell when returning back to the table view in -viewWillAppear:animated.

[self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:YES];

I also need to reload the table view's data in this case but when you do that it clears the selected state of the selected cell so you don't see any fade animation.

Is there a way to reload the table data and also preserve the selected state to create the deselect animation?

Berry Blue
  • 15,330
  • 18
  • 62
  • 113
  • NSUserDefaults too heavy for this? – soulshined Dec 30 '14 at 20:11
  • See http://stackoverflow.com/questions/6649202/uitableview-doesnt-keep-row-selected-upon-return – Mike Taverne Dec 30 '14 at 20:24
  • @MikeTaverne the problem isn't maintaining the selection state, the problem is turning it off in an animated manner upon `viewWillAppear` while _also_ reloading the data. The only way I've figured out how to maintain the animation is to either reload the table in `viewWillAppear` and do the animation in `viewDidAppear`, or vice versa. – Stonz2 Dec 30 '14 at 20:29
  • Interesting, OK. I thought that post suggested a technique for manually selecting the row after reload. If you do that, and then your deselect with animation, does that give the effect you want? – Mike Taverne Dec 30 '14 at 20:31

5 Answers5

4

After several attempts, I've found something that works. You need to set the deselection to occur after a "delay" (of 0 seconds) in order to make sure it happens on the next draw cycle and gets animated properly.

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    NSIndexPath *indexPath = self.tableView.indexPathForSelectedRow;
    [self.tableView reloadData];
    [self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];

    [self performSelector:@selector(deselectRow) withObject:nil afterDelay:0];

}

- (void)deselectRow
{
    [self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:YES];
}
Stonz2
  • 6,306
  • 4
  • 44
  • 64
1

Try this in your viewDidLoad:

    [self setClearsSelectionOnViewWillAppear:NO];
Mike Taverne
  • 9,156
  • 2
  • 42
  • 58
  • This does not help when reloading the table in `viewWillAppear` as the reload will clear the selected cell. – Stonz2 Dec 30 '14 at 20:36
1

The obvious solution suggested by @user2970476 seems to work fine on iOS 7. For iOS 8 I slightly modified @Stonz2's answer to use blocks

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    dispatch_async(dispatch_get_main_queue(), ^(void) {     // necessary for iOS 8
        [self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:YES];
    });
}

I also had to set self.clearsSelectionOnViewWillAppear = NO; in viewDidLoad because the IB setting got ignored.

Sebastian
  • 2,109
  • 1
  • 20
  • 15
0

You will need to reload your table view first, select the row you want to indicate then perform the deselect animation. The issue you are having is your order of operation is incorrect.

Kyle Richter
  • 450
  • 2
  • 6
  • I've tried this. I reload, set the cell selected again (reload clears it) without animation, and then set unselected with animation. It doesn't animate. – Stonz2 Dec 30 '14 at 20:35
  • @BerryBlue Could be a timing issue. Have you tried performing the deselection in `viewDidAppear`? – jlehr Dec 30 '14 at 20:48
0

You can save the current selection with

NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
[self.tableView reloadData];
[self.tableView selectRowAtIndexPath:selectedRow animated:NO scrollPosition:UITableViewScrollPositionNone];
  • As stated in a comment on another answer a few minutes ago, this has been tried. The deselection still does not animate. – Stonz2 Dec 30 '14 at 20:38