UITableViewCell重用:单元格显示不正确 - 未按预期重复使用

时间:2013-04-03 02:30:45

标签: iphone ios xcode uitableview

我创建了一个多选列表,允许选择多种成分。

在我的tableview中,可以根据Ingredient的list属性启用或禁用单元格。如果设置了Ingredient的list属性,则将禁用该单元格。

然而,当重新使用一个单元格时,它不会像我期望的那样显示。下面的图片比我能更有效地解释问题。

(不应该启用的成分是:蛋糕糖霜,炼乳和Cournflour。)

  1. 第一张图片显示三种成分已禁用并按预期注释。

  2. 然而,在第二张图片中,向下滚动显示某些成分被显示为已禁用(但您可以选择它们,并且它们具有完全交互)。

  3. 第三张图片显示滚动回到顶部后的列表。有些成分已经变灰,并注意到Cornflour显示为已启用,即使您无法互动/选择它。

  4. 问题与细胞重用有关。看起来这个单元在重复使用时没有被“重置”,因此保持了一些“旧”外观。

    下面是来自cellForRowAtIndexPath:的代码,因为我确定这就是问题所在(尽管我看不出有什么问题)。

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *CellIdentifier = @"Cell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    
        if (cell == nil)
        {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
        }    
    
        // Fetches the corresponding Ingredient from the ingredientArray
        Ingredient *ingredient = [self.ingredientArray objectAtIndex:indexPath.row];
    
        if ([ingredient.list isEqualToString:@"Lardr"])
        {
            cell.userInteractionEnabled = NO;
            cell.detailTextLabel.text = @"   Already in your Lardr";
        }
        else if ([ingredient.list isEqualToString:@"Shopping List"])
        {
            cell.userInteractionEnabled = NO;
            cell.detailTextLabel.text = @"   Already on your Shopping List";
        }
        else
        {
            cell.userInteractionEnabled = YES;
            cell.detailTextLabel.text = @"";
        }
    
        // Add a checkmark accessory to the cell if the ingredient is on the selectedIngredients array
        if ([self.selectedIngredients containsObject:ingredient])
            cell.accessoryType = UITableViewCellAccessoryCheckmark;
        else
            cell.accessoryType = UITableViewCellAccessoryNone;
    
        cell.textLabel.text = ingredient.name;
    
        return cell;
    }
    

    我正在努力解决这个问题,并且我已经阅读了所有甚至远程相关的SO问题,但无济于事。有什么问题?!


    我的逻辑是,对于每个单元格,设置textLabel,detailTextLabel,userInteractionEnabled和accessoryType属性,无论通过if语句执行哪条路径,所以我看不出为什么,即使重用后,单元格也不是正确显示。


    编辑:为了找出问题的根源,我尝试通过在获取相应成分的行上方添加以下内容,将单元格“重置”回默认值:但无济于事。

    cell.userInteractionEnabled = YES;
    cell.textLabel.text = nil;
    cell.detailTextLabel.text = nil;
    cell.accessoryType = UITableViewAccessoryNone;
    

    然而,有趣且完全不合逻辑的 - 当我将以下行cell.textLabel.text = ingredient.name移动到读取Ingredient *ingredient = [self.ingredientArray objectAtIndex:indexPath.row];的行的正下方时,绝对没有样式应用于任何单元格,即使userInteraction是进一步设置如下(相关单元格按预期禁用)。

    我在想,细胞属性的设置顺序是否重要?我知道它不应该,但外观根据上述情况而变化。


    更新:我已经解决了这个问题;请参阅下面的答案。

4 个答案:

答案 0 :(得分:2)

willDisplayCell

中明确设置单元格的颜色
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{

 Ingredient *ingredient = [self.ingredientArray objectAtIndex:indexPath.row];

    if ([ingredient.list isEqualToString:@"Lardr"])
    {
        cell.textLabel.textColor = [UIColor lightGrayColor];
    }
    else if ([ingredient.list isEqualToString:@"Shopping List"])
    {
        cell.textLabel.textColor = [UIColor lightGrayColor];
    }
    else
    {
        cell.textLabel.textColor = [UIColor blackColor];
    }

}

答案 1 :(得分:2)

我已经解决了这个问题。问题是我在设置单元格的文本之前设置了userInteractionEnabled(感谢评论中Carl Veazey的link)。

我通过在调整userInteractionEnabled属性之前设置单元格的文本来解决问题。但是,没有样式应用于单元格(即使单元格被禁用)。因此,我不得不通过设置单元格的textColor手动设置单元格的样式。以下是带注释的调整后的代码。

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

    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    } 

    // Fetches the relevent ingredient from the ingredientArray
    Ingredient *ingredient = [self.ingredientArray objectAtIndex:indexPath.row];
    cell.textLabel.text = ingredient.name; // Moved this line before setting userInteractionEnabled

    if ([ingredient.list isEqualToString:@"Lardr"])
    {
        cell.userInteractionEnabled = NO;
        cell.detailTextLabel.text = @"   Already in your Lardr";
        cell.textLabel.textColor = [UIColor grayColor]; // Update the color accordingly
    }
    else if ([ingredient.list isEqualToString:@"Shopping List"])
    {
        cell.userInteractionEnabled = NO;
        cell.detailTextLabel.text = @"   Already on your Shopping List";
        cell.textLabel.textColor = [UIColor grayColor];
    }
    else
    {
        cell.userInteractionEnabled = YES;
        cell.detailTextLabel.text = @"";
        cell.textLabel.textColor = [UIColor blackColor];
    }

    // Add a checkmark accessory to the cell if the ingredient is on the selectedIngredients array
    if ([self.selectedIngredients containsObject:ingredient])
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    else
        cell.accessoryType = UITableViewCellAccessoryNone;

    return cell;
}

显然,设置单元格属性的顺序应该是无关紧要的,所以我确定这是一个错误。希望这对遇到同样问题的其他人有帮助。

答案 2 :(得分:0)

在表格视图中维护所选单元格的列表,同时重新使用单元格只检查单元格是否已在选择列表中。如果是,只需在那里进行自定义。试试这样吧。

宣言

 TableViewCell *_selectedCell; 

自定义行以存储选定的单元格并维护选择列表。

_selectedCell = (TableViewCell*)[self.ItemTable cellForRowAtIndexPath:[NSIndexPath indexPathForRow:rowIndex inSection:0]];

在cellForRowAtIndexPath中检查当前单元格是否在

if(_selectedCell)
        [cell setBackgroundColor:[UIColor whiteColor]];// Customize the cell 

答案 3 :(得分:0)

将以下代码与故事板中的表视图控制器一起使用,一切正常。在不使用故事板的情况下,默认情况下,表格视图中存在一些错误:

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

    // Fetches the corresponding Ingredient from the ingredientArray
    Ingredient *ingredient = [self.ingredientArray objectAtIndex:indexPath.row];

    if ([ingredient.list isEqualToString:@"Lardr"])
    {
        cell.userInteractionEnabled = NO;
        cell.detailTextLabel.text = @"   Already in your Lardr";
        cell.textLabel.textColor = [UIColor lightGrayColor];
    }
    else if ([ingredient.list isEqualToString:@"Shopping List"])
    {
        cell.userInteractionEnabled = NO;
        cell.detailTextLabel.text = @"   Already on your Shopping List";
        cell.textLabel.textColor = [UIColor lightGrayColor];
    }
    else
    {
        cell.userInteractionEnabled = YES;
        cell.detailTextLabel.text = @"";
        cell.textLabel.textColor = [UIColor blackColor];
    }

    if ([self.selectedIngredients containsObject:ingredient])
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    else
        cell.accessoryType = UITableViewCellAccessoryNone;

    cell.textLabel.text = ingredient.name;

    return cell;
}

请注意,我使用dequeueReusableCellWithIdentifier:forIndexPath:而不是dequeueReusableCellWithIdentifier:,并删除if子句。这与您的问题没有任何关系,但这是在故事板中为表视图执行此操作的最新方法。