Why is -didDeselectRowAtIndexPath not being called?

I created a fresh project (Xcode 4, Master-Detail application) just to see if I'm doing something wrong, but I still have the same problem. I want to call -reloadData when the user deselects a cell, so this is my code:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    NSLog(@"%s", __PRETTY_FUNCTION__);
}

-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"%s", __PRETTY_FUNCTION__);
    [tableView reloadData];
}

-(NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"%s", __PRETTY_FUNCTION__);
    return indexPath;
}

The problem is that didDeselectRowAtIndexPath and willDeselectRowAtIndexPath don't seem to be called. Is this the expected behavior? The docs for tableView:didDeselectRowAtIndexPath: state

Tells the delegate that the specified row is now deselected.

so I guess that it should work as I thought.


Solution 1:

If you call deselectRowAtIndexPath:animated:, the delegate methods tableView:willDeselectRowAtIndexPath: and tableView:didDeselectRowAtIndexPath: message are not sent.

Solution 2:

the documentation of tableView:willDeselectRowAtIndexPath: also says that

This method is only called if there is an existing selection when the user tries to select a different row. The delegate is sent this method for the previously selected row. You can use UITableViewCellSelectionStyleNone to disable the appearance of the cell highlight on touch-down.

It not worked for we when I used UITableViewCellSelectionStyleNone.

Solution 3:

One other quirk that I've found — in IOS 5.1, at any rate — is that if you call reloadData on the table, you won't get didDeselectRowAtIndexPath for any selected rows. In my case, I adjust the cell layout slightly depending on whether it's selected or not, so I needed to manually do that work prior to reloading the table data.

Solution 4:

I know this is an old question but I just ran into the same problem.

If you use

[tableView reloadData]

Then The table data is reloaded and no rows are selected behind the scenes - meaning

only

didSelectRowAtIndexPath

is ever called. I hope this helps someone who comes across this problem.

Solution 5:

A clean way of solving this problem is to do the following:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath)
    // Do your cell setup work here...

    //If your cell should be selected...
    if cellShouldBeSelected {
        tableView.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: UITableViewScrollPosition.None)
    }

    return cell
}

This solves this entire problem of a cell not responding to being deselected after a tableView.reloadData()call happens.