2013-04-03 29 views
7

我创建了一个多选列表,允许选择多种成分。UITableViewCell重用:单元格显示不正确 - 没有按预期重用

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

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

(不应该被使能的成分有:锦上添花,炼乳和Cournflour。)

  1. 第一个图像显示禁止,如预期注释的三种成分。

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

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

问题是关于细胞再利用。看起来单元格在重用时没有被“重置”,因此保留了一些“旧”的外观。

以下是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; 
} 

我在我束手无策试图弄清楚这一点,和我读过这一切都让甚至远程相关的问题,但都无济于事。有什么问题?!


我的逻辑是,每个单元中,为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];,绝对没有的造型适用于任何细胞,即使用户交互设置下面进一步行(并按预期禁用相关单元)。

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


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

+0

你在使用StoryBoards吗? –

+0

什么是文字灰色? –

+0

您发布的代码没有任何问题。将用户交互设置为NO不会使文本变灰。我认为你的问题可能在于你用什么方法来做到这一点。 – rdelmar

回答

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; 
} 

显然,在其中设置一个单元格的属性的顺序应该是不相关的,所以我敢肯定,这是一个错误。希望这有助于遇到同样问题的其他人。

0

在表格视图中维护选定单元格的列表,而重用单元格只检查单元格是否已在选择列表中。如果是,只要在那里做你的定制。像这样尝试。

宣言

TableViewCell *_selectedCell; 

定制来存储所选择的小区和维持选择表中的行。

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

在的cellForRowAtIndexPath检查当前小区处于

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

使用从故事板的表视图控制器下面的代码,一切都工作得很好。它似乎有与没有使用故事板的时候,你在默认情况下得到的表视图一些bug:

-(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:和消除,如果条款。这与您的问题没有任何关系,但它是在故事板中为表格视图执行此操作的最新方式。

+0

你是否证明了这个错误?换句话说,你是否见证了这个代码在应用于故事板和非故事板表时的工作方式不同?这将是非常令人惊讶的。 – danh

+0

@danh,是的,我已经使用上面几乎相同的代码演示了该bug - 因为它没有故事板,所以我添加了通常的if(cell == nil)子句。但除此之外,代码与我上面发布的代码完全相同。我只是在应用程序委托中初始化了一个表视图控制器,并且我看到了与OP发布的行为相同的行为。 – rdelmar

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

我刚刚实施了您的建议。它仍然没有解决问题。 – TeaPow

+0

我想在我的单元格和cellForRowAtIndexPath中设置背景颜色,但它不起作用,但是它的作用就像一个魅力。谢谢 –

相关问题