Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITableViewCell setSelected:animated: not working

This is driving me crazy. I've looked here on S.O. for what I thought was a simple answer but couldn't find one.

In my custom UITableViewCell:

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{   
    // Configure the view for the selected state
    if (selected) {        
        [self.languageLevelNameLabel setTextColor:[UIColor blackColor]];        
    }
    else {        
        [self.languageLevelNameLabel setTextColor:[UIColor colorMessageCountZero]];
    }

    [self setNeedsDisplay];
}

In tableView:cellForRowAtIndexPath: of the controller:

 if ([level integerValue] == indexPath.row) {

        [cell setSelected:YES];
    }

I've inserted break points and selected == YES is getting passed for the correct cell, and the if statement is being executed when it should be, but the text never gets set to blackColor.

like image 371
OdieO Avatar asked Mar 27 '14 20:03

OdieO


2 Answers

For the cell to appear selected, you have to call -setSelected:animated: from within -tableView:willDisplayCell:forRowAtIndexPath: like so:

Objective C:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (/* should be selected */) {
        [cell setSelected:YES animated:NO];
        [tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];  // required, as noted below
    }
}

Swift 3:

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if (/* should be selected */) {
        cell.setSelected(true, animated: false)
        tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)  // required, as noted below
    }
}

Calling -setSelected from anywhere else has no effect.

Why? After initializing or dequeueing a cell, but before displaying it, the table view calls a private method called -_configureCellForDisplay:forIndexPath: which, among other things, sets the cell's selected property to NO. The delegate's willDisplayCell:forRowAtIndexPath: gets called after this, letting you set anything needed for display.

like image 184
Drew C Avatar answered Nov 15 '22 07:11

Drew C


If you want to set your cell as selected use the method selectRowAtIndexPath:animated:scrollPosition: like this in your cellForRowAtIndexPath method of your table view

Objective-C

[self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];

swift 4

tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
like image 43
Fran Martin Avatar answered Nov 15 '22 05:11

Fran Martin