kusumoto_teruya
kusumoto_teruya

Reputation: 2475

put check mark on UITableViewCell when tapping the cell

I want to put check mark on UITableViewCell when tapping the cell.

But when tapping a cell and scrolling tableView, other cell is also put check mark.

(I think it's because UITableViewCell is reused.)

I have this code.

ViewController.m

@property (nonatomic, strong) NSMutableArray* selectedItems;

- (void)viewDidLoad
{
    NSUserDefaults* ud = [NSUserDefaults standardUserDefaults];
    self.selectedItems = [NSMutableArray array];
    if ([ud objectForKey:@"SelectedItems"] != nil) {
        self.selectedItems = [ud objectForKey:@"SelectedItems"];
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString* cellIdentifier = @"Cell";
    CustomCell* cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil) {
        cell = [[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
    }
    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    if (cell.isChecked == YES) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }else if (cell.isChecked == NO) {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }    
    return cell;
}

//when tapping the cell, put a check mark
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    CustomCell* cell = (CustomCell *)[tableView cellForRowAtIndexPath:indexPath];
    cell.isChecked = YES;
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
    [self.selectedItems addObject:cell.titleLabel.text];
    NSUserDefaults* ud = [NSUserDefaults standardUserDefaults];
    [ud setObject:self.selectedItems forKey:@"SelectedItems"];
    [ud synchronize];
}

CustomCell.h

@property BOOL isChecked;

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier;


I'd like to put a check mark on only selected cell.
How do I fix it?

Upvotes: 0

Views: 178

Answers (4)

Fahim Parkar
Fahim Parkar

Reputation: 31637

Remove/ Comment if (cell == nil) { & you are done..

This is happening because cell is being re-used.

Upvotes: 0

SandeepAggarwal
SandeepAggarwal

Reputation: 1293

Since cell is reusable the "isChecked" property you are using also remains intact with the cell hence to check the selection of cell you have to track the 'indexPath' property of the cell.

Declare a property lastIndexPath to track the tapped cell

@property NSIndexPath* lastIndexPath;


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

    // Configure the cell...


    if ([indexPath compare:self.lastIndexPath] == NSOrderedSame)
    {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    }
    else
    {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }
}


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

    [self.selectedItems addObject:cell.titleLabel.text];
    NSUserDefaults* ud = [NSUserDefaults standardUserDefaults];
    [ud setObject:self.selectedItems forKey:@"SelectedItems"];
    [ud synchronize];

}

Upvotes: 0

Mundi
Mundi

Reputation: 80265

The problem is that you are storing the checked/unchecked information in your cell which is the view rather than your data source, thus violating a fundamental principle of the MVC (model-view-controller) paradigm.

Instead, in your cellForRowAtIndexPath you have to check the data you stored in the user defaults and then decide if the cell should be checked.

Also, rather than accessing user defaults for each cell, let's assume you have an instance variable in your class that reads from the user defaults when the view loads. Suppose also, that your data source has this structure (array of dictionaries):

@[@"text" : @"firstCellText",  @"checked" : @NO},
  @"text" : @"secondCellText", @"checked" : @YES}]

You can of course do this in a myriad of different ways, so the above is just for illustration.

// cellForRowAtIndexPath
cell.accessoryType = 
 [datasource[indexPath.row][@"checked"] boolValue] ?
 UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;

Upvotes: 2

Teodor Ciuraru
Teodor Ciuraru

Reputation: 3477

You should keep a variable that tells you that the cell has been tapped and check constantly of its state in didSelectRow.

Check: Issue while reusing table view cell?

Upvotes: 0

Related Questions