Reputation: 2475
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
Reputation: 31637
Remove/ Comment if (cell == nil) {
& you are done..
This is happening because cell is being re-used.
Upvotes: 0
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
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
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