简体   繁体   中英

UITableView ticks cells randomly when they leave the frame

I have a UITableView in which you can only tick 4 cells. If I tick a certain amount of cells and then scroll up or down, it will tick random cells. I don't understand the logic behind this because the only method I use for ticking is DidSelectRowAtIndex which doesn't get executed (I put a breakpoint in there to check it). I really do not know what could be causing this but here is cellForRowAtIndex:

- (UITableViewCell *) tableView: (UITableView *) tableView
          cellForRowAtIndexPath: (NSIndexPath *) indexPath
{

        static NSString *cellName = @"PrefsTableViewCell";

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:
                                 cellName];
        if (cell == nil)
        {
                cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellName] autorelease];
        }

        NSUInteger row = [indexPath row];
        Drink *drink = [drinks objectAtIndex:row];

        cell.textLabel.text = drink.name;
        cell.detailTextLabel.text = [NSString stringWithFormat:@"%d", drink.caffeine];
        [[cell imageView] setImage:drink.image];

        return cell;
}

I'm having a feeling that it has something to do with this but I can't really tell.

This is what it looks like prior to scrolling:

在此输入图像描述

This is what happens when I scroll up to the top:

在此输入图像描述

I did not click that top one. If I scroll down and up again it's likely to get unticked and another one will get ticked.

It may be important so here is the didSelectRowAtIndexPath method:

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

        NSLog(@"TESTING");

        if ((cell.accessoryType == UITableViewCellAccessoryNone) && [[DataContainerSingleton theDataContainerSingleton].favourites count] < 4)
        {
                cell.accessoryType = UITableViewCellAccessoryCheckmark;

                [[DataContainerSingleton theDataContainerSingleton].favourites addObject:[drinks objectAtIndex:indexPath.row]];
                NSLog(@"CHECKED %d", [[DataContainerSingleton theDataContainerSingleton].favourites count]);
        }
        else if (cell.accessoryType == UITableViewCellAccessoryCheckmark)
        {
            for (int i = 0; i < [[DataContainerSingleton theDataContainerSingleton].favourites count]; i++)
            {
                NSString *drinkName = [[drinks objectAtIndex:indexPath.row] name];
                NSString *favName = [[[DataContainerSingleton theDataContainerSingleton].favourites objectAtIndex:i] name];

                if ([drinkName isEqualToString: favName])
                {
                    cell.accessoryType = UITableViewCellAccessoryNone;
                    [[DataContainerSingleton theDataContainerSingleton].favourites removeObjectAtIndex:i];
                    NSLog(@"UNCHECKED %d", [[DataContainerSingleton theDataContainerSingleton].favourites count]);
                }
            }

        }
}

You are not saving which items have been ticked. You should save the indexes in an array, and set the tick in cellForRowAtIndexPath: . Something like-

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];

        if(![self.tickedIndexPaths containsObject:indexPath]) //tickedIndexPaths is an array
            [self.tickedIndexPaths addObject:indexPath];
        else
            [self.tickedIndexPaths removeObject:indexPath];
}

Then-

- (UITableViewCell *) tableView: (UITableView *) tableView
          cellForRowAtIndexPath: (NSIndexPath *) indexPath
{

        static NSString *cellName = @"PrefsTableViewCell";

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:
                                 cellName];
        if (cell == nil)
        {
                cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellName] autorelease];
        }

        NSUInteger row = [indexPath row];
        Drink *drink = [drinks objectAtIndex:row];

        cell.textLabel.text = drink.name;
        cell.detailTextLabel.text = [NSString stringWithFormat:@"%d", drink.caffeine];
        [[cell imageView] setImage:drink.image];

        if([self.tickedIndexPaths containsObject:indexPath])
        {
              cell.accessoryType = UITableViewCellAccessoryCheckmark;
        }
        else
        {
              cell.accessoryType = UITableViewCellAccessoryNone;
        }

        return cell;
}

Keep in mind that due to the reuse of cells, the last else block is very important.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM