Reputation: 1404
This is my code, which shows a problem for 14 rows of a table view. For one screen, 6 cells are visible.
When I tapped the 2nd cell, the 10 cell also has a checkmark, tap 3rd then 11th checkmarked, 1st then 9th checkmarked, tap 1st, then 8th also checkmarked...but the grey highlight does not behave like this, only one cell can be highlighted.
If I tap a cell after one is tapped on the the same screen, the one just checkmarked will be cleared for checkmark, which makes sense. However, if after I tapped one cell and then scroll the tableview lower, I can tap a cell and it shows checkmark as well, i.e. the one just checked on top screen still has a checkmark. So if I scroll up and down, and tap one cell each time after I scroll to the other side, I can put a checkmark for every cell, all checkmarks are shown.
It is really weird, and I have tried a lot of ways to solve it, but seems I have some basic understanding of UITableView
missing, can anyone figure it out, please? Thanks.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ID= @"UITableViewCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
}
cell.imageView.image = [UIImage imageNamed:@"earth.png"];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell =[tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell =[tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
}
Upvotes: 2
Views: 671
Reputation: 234
Stonz2's answer is right. For example, you should create an object for table view data source and it should has a property to show is it checkmarked.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
...
Item *item = [self.itemArray objectAtIndex:indexPath.row];
if (item.checkmarked) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:NO];
Item *tappedItem = [self.itemArray objectAtIndex:indexPath.row];
tappedItem.checkmarked = !tappedItem.checkmarked;
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
Upvotes: 1
Reputation: 6396
You're not storing the existence/absence of your checkmark in any sort of persisted data source and showing/hiding it in cellForRowAtIndexPath
. Because of this, your table is reusing your cells, and it just throws it up as it found it. So if it reuses a cell that had your checkmark accessory enabled, it shows it as enabled (because you didn't specifically disable it in cellForRow
)
I would keep an NSMutableArray
of selected indexPath
objects. Add the indexPath
in didSelectRowAtIndexPath
, and remove it in didDeselectRowAtIndexPath
. Then, in cellForRowAtIndexPath
, check if the current indexPath
exists in the array and enable the checkmark if so, disable if not.
Upvotes: 5