Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITableViewController changing one reusable cell affects other cells

I have a very simple UITableViewController subclass designed to show users the characters in the alphabet in cells. When the user presses on a cell, it is to set its accessory type to a checkmark.

#import "MTGTableViewController.h"

@interface MTGTableViewController ()

@property (nonatomic, strong) NSArray *data;

@end

@implementation MTGTableViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    _data = @[@"A", @"B", @"C", @"D", @"E", @"F", @"G", @"H", @"I", @"J", @"K", @"L", @"M", @"N", @"O", @"P", @"Q", @"R", @"S", @"T", @"U", @"V", @"W", @"X", @"Y", @"Z"];
}

#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 _data.count;
}


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

    // Configure the cell...
    cell.textLabel.text = _data[indexPath.row];

    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
}

@end

The table view works fine. I have my reuseIdentifier property set in the storyboard on my prototype cells, and it all looks good before I start selecting cells.

The problem: When I select any cell, say the "A" cell, other not-yet-visible cells are also given checkmarks when i scroll down to them. Even worse, when I scroll up and down, sometimes the checkmark on cell "A" is removed and given to cell "B".

like image 225
michaelsnowden Avatar asked Jul 15 '14 20:07

michaelsnowden


1 Answers

This is because of the way table views reuse cells. You need to make sure to clear the accessory item after you call dequeueReusableCellWithIdentifier. eg:

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

    // Configure the cell...
    cell.textLabel.text = _data[indexPath.row];
    cell.accessoryType = UITableViewCellAccessoryNone;

    return cell;
}

Although--you're going to have a different problem after you make this change. The cell is going to "forget" that it is selected because of this code. So you'll need to actually change that line where the accessoryType is set to check and see if the cell is selected or not.

like image 94
Nicholas Hart Avatar answered Oct 12 '22 23:10

Nicholas Hart