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

Iphone UITableViewCell重用:单元格显示不正确-未按预期重用,iphone,ios,xcode,uitableview,Iphone,Ios,Xcode,Uitableview,我已经创建了一个多选择列表,允许选择多种成分 在我的tableview中,可以根据成分的列表属性启用或禁用单元格。如果设置了成分列表属性,则单元格将被禁用 然而,当一个单元格被重复使用时,它并不像我期望的那样显示。下面的图片比我能更有效地解释这个问题 不应启用的成分有:蛋糕糖霜、炼乳和古恩面粉 第一幅图显示了按预期禁用和注释的三种成分 然而,在第二幅图中,向下滚动显示某些成分被禁用,但您可以选择它们,它们具有完全的交互作用 第三幅图显示了向上滚动到顶部后的列表。有些配料已灰显,请注意玉米粉是如何

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

在我的tableview中,可以根据成分的列表属性启用或禁用单元格。如果设置了成分列表属性,则单元格将被禁用

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

不应启用的成分有:蛋糕糖霜、炼乳和古恩面粉

第一幅图显示了按预期禁用和注释的三种成分

然而,在第二幅图中,向下滚动显示某些成分被禁用,但您可以选择它们,它们具有完全的交互作用

第三幅图显示了向上滚动到顶部后的列表。有些配料已灰显,请注意玉米粉是如何显示为启用的,即使您无法交互/选择它

问题在于单元重用。在重复使用时,单元似乎没有被重置,因此保留了一些旧的外观

下面是CellForRowatineXpath:中的代码,我确信这就是问题所在,尽管我看不出哪里出了问题

- (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;
}
我绞尽脑汁想弄明白这一点,我读了这么多的问题,这些问题甚至有点牵连,但都没有用。怎么了

我的逻辑是,对于每个单元格,设置textLabel、detailTextLabel、userInteractionEnabled和accessoryType属性,无论通过if语句的执行路径是什么,因此我不明白为什么即使在重用之后,单元格也不能正确显示

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

cell.userInteractionEnabled = YES;
cell.textLabel.text = nil;
cell.detailTextLabel.text = nil;
cell.accessoryType = UITableViewAccessoryNone;
然而,有趣且完全不合逻辑的是——当我将下面的行cell.textlab.text=component.name移到component*component=[self.ingredientArray objectAtIndex:indexPath.row]的正下方时;,绝对不会对任何单元格应用任何样式,即使下面进一步设置了userInteraction,并且按照预期禁用了相关单元格

我在想,细胞属性设置的顺序重要吗?我知道不应该,但外观会根据上述情况发生变化


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

在表视图中维护选定单元格的列表,在重用该单元格时,只需检查该单元格是否已在选择列表中。如果是的话,就在那边定制一下。像这样试试

声明

 TableViewCell *_selectedCell; 
自定义行以存储选定单元格并维护选择列表

_selectedCell = (TableViewCell*)[self.ItemTable cellForRowAtIndexPath:[NSIndexPath indexPathForRow:rowIndex inSection:0]];
在cellForRowAtIndexPath中检查当前单元格是否位于

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

使用下面的代码和故事板中的表视图控制器,一切正常。在不使用情节提要时,默认情况下得到的表视图似乎存在一些错误:

-(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子句。这与您的问题没有任何关系,但这是为故事板中的表视图执行此操作的最新方法。

在willDisplayCell中显式设置单元格的颜色


我已经解决了这个问题。问题是,我在设置单元格文本之前设置了userInteractionEnabled,这要感谢Carl Veazey在评论中给出的提示

- (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;
}
我通过在调整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;
}

显然,设置单元格属性的顺序应该是不相关的,因此我确信这是一个bug。希望这对遇到同样问题的其他人有所帮助。

您使用的是故事板吗?是什么使文本变灰了?您发布的代码没有问题。将用户交互设置为“否”不会使文本变为灰色。我认为你的问题可能在于你使用的任何方法。@rdelmar我也是这么想的。。。但是在单元格上启用userInteractionEnabled确实会使文本变灰,我只是尝试了一下。而且,我可以报告你能想象到的最基本的表视图应用程序也有同样的问题。@Carlvaezey,真的吗?我也试过了,但没有变灰。你演示过这个bug吗?换句话说,当应用于情节提要表和非情节提要表时,您是否看到此代码的工作方式有所不同?这将非常令人惊讶。@danh,是的,我已经用上面几乎相同的代码演示了这个bug-因为它没有故事板,我添加了通常的if cell==nil clau
东南方。但除此之外,代码与我上面发布的代码完全相同。我刚刚在应用程序委托中分配了一个表视图控制器,我看到了与OP发布的相同的行为。我刚刚实现了你的建议。它仍然没有解决问题。我想在我的手机和cellForRowAtIndexPath上设置背景色,但它不起作用,但有了它,它就像一个符咒。非常感谢。