xcode UITableViewCell Reuse:单元格显示不正确 - 没有按预期重用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15777890/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UITableViewCell Reuse: cell displaying incorrectly - not being reused as expected
提问by TeaPow
I've created a multi-selection list that allows the selection of multiple Ingredients.
我创建了一个多选列表,允许选择多个成分。
In my tableview, cells can either be enabled or disabled based on the list property of an Ingredient. If the Ingredient's list property is set, the cell will be disabled.
在我的 tableview 中,可以根据成分的列表属性启用或禁用单元格。如果设置了成分列表属性,单元格将被禁用。
However, when a cell is re-used, it's not displaying as I would expect. The images below explain the problem more effectively than I can.
但是,当一个单元格被重新使用时,它不会像我期望的那样显示。下面的图片比我更有效地解释了这个问题。
(The ingredients that should not be enabled are: Cake Icing, Condensed Milk and Cournflour.)
(不应该启用的成分是:蛋糕糖霜、炼乳和面粉。)
The first image shows the three Ingredients disabled and annotated as expected.
However, in the second image, scrolling down reveals that some Ingredients are shown to be disabled (but you can select them, and they have full interaction).
The third image shows the list after scrolling back up to the top. Some Ingredients have been greyed out, and notice how Cornflour is displayed as enabled, even though you can't interact/select it.
第一张图片显示了三个已禁用的成分,并按预期进行了注释。
然而,在第二张图片中,向下滚动显示某些成分显示为禁用(但您可以选择它们,并且它们具有完全交互)。
第三张图显示了向上滚动到顶部后的列表。某些成分已变灰,请注意玉米粉如何显示为已启用,即使您无法交互/选择它。
The issue is to do with cell reuse. It appears that the cell is not getting "reset" when reused, and so is keeping some of its "old" appearance.
问题与单元重用有关。似乎电池在重新使用时没有“重置”,因此保留了它的一些“旧”外观。
Below is the code from cellForRowAtIndexPath:
, as I'm sure this is where the problem is (although I can't see what's wrong).
下面是来自 的代码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;
}
I'm at my wit's end trying to figure this out, and I've read all SO questions that are even remotely related, but to no avail. What's the problem?!
我已经竭尽全力试图解决这个问题,我已经阅读了所有甚至远程相关的 SO 问题,但无济于事。有什么问题?!
My logic is that for each cell, the textLabel, detailTextLabel, userInteractionEnabled and accessoryType properties are set, no matter which execution path through the if statements, so I can't see why, even after reuse, the cell isn't displaying correctly.
我的逻辑是,对于每个单元格,设置 textLabel、detailTextLabel、userInteractionEnabled 和附件类型属性,无论通过 if 语句的哪个执行路径,所以我看不出为什么,即使在重用后,单元格也没有正确显示。
EDIT:In an attempt to figure out the root of the problem, I've tried "resetting" the cell back to it's default by adding the following right above the line which fetches the corresponding Ingredient: but to no avail.
编辑:为了找出问题的根源,我尝试通过在获取相应成分的行上方添加以下内容来将单元格“重置”回默认值:但无济于事。
cell.userInteractionEnabled = YES;
cell.textLabel.text = nil;
cell.detailTextLabel.text = nil;
cell.accessoryType = UITableViewAccessoryNone;
However, what is interesting and completely illogical -- when I moved the following line cell.textLabel.text = ingredient.name
to directly underneath the line that reads Ingredient *ingredient = [self.ingredientArray objectAtIndex:indexPath.row];
, absolutely NO styling is applied to any cell, even though userInteraction is set further below (and the relevant cells are disabled as expected).
然而,有趣且完全不合逻辑的事情——当我将以下行移动cell.textLabel.text = ingredient.name
到读取的行正下方时Ingredient *ingredient = [self.ingredientArray objectAtIndex:indexPath.row];
,绝对没有样式应用于任何单元格,即使 userInteraction 在下面进一步设置(并且相关单元格按预期禁用) .
I'm thinking, does the order in which a cells properties are set matter? I know it shouldn't, but the appearance changes based on the above.
我在想,设置单元格属性的顺序重要吗?我知道它不应该,但外观会根据上述情况发生变化。
Update: I've solved the issue; see my answer below.
更新:我已经解决了这个问题;请参阅下面的我的答案。
采纳答案by TeaPow
I've solved the issue. The problem was that I was setting userInteractionEnabled BEFORE setting the cell's text (thanks to a linkfrom Carl Veazey in the comments).
我已经解决了这个问题。问题是我在设置单元格文本之前设置了 userInteractionEnabled(感谢Carl Veazey 在评论中的链接)。
I fixed the issue by setting the cell's text before adjusting the userInteractionEnabled property. However, there was no styling applied to the cell (even though the cell was disabled). I therefore had to manually style the cell by setting the cell's textColor. Below is the adjusted code with comments.
我通过在调整 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;
}
Obviously, the order in which you set the properties of a cell should be irrelevant, and so I'm sure that this is a bug. Hope this helps for anybody else who runs into the same issue.
显然,设置单元格属性的顺序应该无关紧要,因此我确定这是一个错误。希望这对遇到相同问题的其他人有所帮助。
回答by Mihir Mehta
Set your cell's color explicitly in willDisplayCell
在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];
}
}
回答by Ganapathy
Maintainthe list of selected cell in the table view , while reusing the cell just check the cell is already in selection list. If YES just do your customization over there. Try like this.
在表格视图中维护所选单元格的列表,在重用单元格时只需检查单元格是否已经在选择列表中。如果是,请在那里进行自定义。像这样尝试。
Declaration
宣言
TableViewCell *_selectedCell;
Customize the line to store the selected cell and maintain the selection list .
自定义行以存储所选单元格并维护选择列表。
_selectedCell = (TableViewCell*)[self.ItemTable cellForRowAtIndexPath:[NSIndexPath indexPathForRow:rowIndex inSection:0]];
In cellForRowAtIndexPath check current cell is in the
在 cellForRowAtIndexPath 检查当前单元格是否在
if(_selectedCell)
[cell setBackgroundColor:[UIColor whiteColor]];// Customize the cell
回答by rdelmar
Using the following code with a table view controller from the storyboard, everything worked fine. It seems that there is some bug with the table view that you get by default when not using a storyboard:
将以下代码与故事板中的表视图控制器一起使用,一切正常。在不使用情节提要时,默认情况下您会获得表格视图似乎存在一些错误:
-(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;
}
Notice that I use dequeueReusableCellWithIdentifier:forIndexPath: instead of dequeueReusableCellWithIdentifier:, and eliminate the if clause. This doesn't have anything to do with your problem, but it's the latest way to do it for a table view in a storyboard.
请注意,我使用 dequeueReusableCellWithIdentifier:forIndexPath: 而不是 dequeueReusableCellWithIdentifier:,并消除了 if 子句。这与您的问题没有任何关系,但这是对故事板中的表视图进行处理的最新方法。