我创建了一个多选列表,允许选择多种成分。
在我的tableview中,可以根据Ingredient的list属性启用或禁用单元格。如果设置了Ingredient的list属性,则将禁用该单元格。
然而,当重新使用一个单元格时,它不会像我期望的那样显示。下面的图片比我能更有效地解释问题。
(不应该启用的成分是:蛋糕糖霜,炼乳和Cournflour。)
第一张图片显示三种成分已禁用并按预期注释。
然而,在第二张图片中,向下滚动显示某些成分被显示为已禁用(但您可以选择它们,并且它们具有完全交互)。
第三张图片显示滚动回到顶部后的列表。有些成分已经变灰,并注意到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;
}
我正在努力解决这个问题,并且我已经阅读了所有甚至远程相关的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是进一步设置如下(相关单元格按预期禁用)。
我在想,细胞属性的设置顺序是否重要?我知道它不应该,但外观根据上述情况而变化。
更新:我已经解决了这个问题;请参阅下面的答案。
答案 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子句。这与您的问题没有任何关系,但这是在故事板中为表视图执行此操作的最新方法。