Search code examples
iosuitableviewreloaddata

How can an UITableViewCell stay highlighted even after reloadData?


If reloadData is called the selected UITableViewCell doesn't stay highlighted. So I have to remember the NSIndexPath of the selected cell (no multiple selection). But if I want to use setHighlighted in cellForRowAtIndexPath than the cell does not get highlighted. If I do this in a method of the UITableViewController then the cell gets highlighted!?

Beside this problem I experienced another thing. I got a kind of multiple selection if I use setHighlighted together with the "normal" selection so that two cells were highlighted at the same time (which they shouldn't). I tried to undo the highlight with deselectRowAtIndexPath but that does nothing. It only works in didSelectRowAtIndexPath with the current index path or outside in a method of UITableViewController only in conjunction with reloadData afterwards.

I'm experiencing this on iOS 7 and iOS 8. Here is a sample code:

- (void)viewDidLoad {
    [super viewDidLoad];

    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"testCell"];

    UIBarButtonItem *anotherButton = [[UIBarButtonItem alloc] initWithTitle:@"Show" style:UIBarButtonItemStylePlain target:self action:@selector(refreshPropertyList:)];
    self.navigationItem.rightBarButtonItem = anotherButton;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

-(void)viewDidLayoutSubviews
{
    if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
        [self.tableView setSeparatorInset:UIEdgeInsetsZero];
    }

    if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
        [self.tableView setLayoutMargins:UIEdgeInsetsZero];
    }
}

-(void)refreshPropertyList:(UIBarButtonItem *)sender {
    [self.tableView reloadData];
    NSIndexPath *temp = [NSIndexPath indexPathForRow:0 inSection:0];
    UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:temp];
    [cell setHighlighted:true];
    self.selectedIndexPath  = temp;
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    return 3;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"testCell" forIndexPath:indexPath];

    if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
        [cell setSeparatorInset:UIEdgeInsetsZero];
    }

    if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
        [cell setLayoutMargins:UIEdgeInsetsZero];
    }
    cell.textLabel.text = @"Test";

    if ([indexPath isEqual:self.selectedIndexPath]) {
        [cell setHighlighted:YES];
    }
    else {
        [cell setHighlighted:NO];
    }

    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    [self.tableView deselectRowAtIndexPath:self.selectedIndexPath animated:false];

    self.selectedIndexPath = indexPath;
}

How can an UITableViewCell stay highlighted even after reloadData?


Solution

  • You can use one line code to select a row

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

    Selected and highlighted are different. So you can't deselect the highlighted state. Visit: https://developer.apple.com/library/ios/documentation/uikit/Reference/UITableViewCell_Class/index.html#//apple_ref/occ/instm/UITableViewCell/setSelected:animated: