UITableViewCell - 如何在重用之前重置内容
Posted
技术标签:
【中文标题】UITableViewCell - 如何在重用之前重置内容【英文标题】:UITableViewCell - how to reset content before reusing 【发布时间】:2015-07-13 05:55:26 【问题描述】:有一个我无法修复的烦人错误。
我有一个CustomCell
,在其中我有一个子视图,可以根据对象的值改变它的颜色。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *cellIdentifier = @"CustomCell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
if (cell == nil)
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
MyObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
if ([object.redColor isEqualToNumber:[NSNumber numberWithBool:YES]])
cell.colorView.backgroundColor = [UIColor redColor];
else
cell.colorView.backgroundColor = [UIColor clearColor];
return cell;
这一切正常,除非我从 tableview 中删除带有redColor = YES
的行,然后滚动显示不可见的行。可见的第一行(重用可重用单元格的第一行)具有红色,即使该行是redColor = NO
。如果我再次滚动并隐藏单元格然后再次显示它,颜色将设置为 clearColor,它应该是这样的。
我认为这是因为它重用了刚刚删除的单元格。
所以我试图在重用之前重置单元格的内容。
在CustomCell.m
- (void)prepareForReuse
[super prepareForReuse];
self.clearsContextBeforeDrawing = YES;
self.contentView.clearsContextBeforeDrawing = YES;
self.colorView.backgroundColor = [UIColor clearColor];
但这不起作用。 苹果文档说
tableView:cellForRowAtIndexPath: 中表格视图的委托在重用单元格时应始终重置所有内容。
重置内容的正确方法是什么?我必须从超级视图中删除子视图吗?
提前致谢
【问题讨论】:
你好@SFF检查我的答案。,,, 【参考方案1】:这似乎行得通。
我在CustomCell.m
CustomCell.m
prepareForReuse 时删除了单元格的 contentView
- (void)prepareForReuse
[super prepareForReuse];
// Clear contentView
BOOL hasContentView = [self.subviews containsObject:self.contentView];
if (hasContentView)
[self.contentView removeFromSuperview];
再次添加到cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
// Cell
static NSString *cellIdentifier = @"CustomCell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
if (cell == nil)
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
// Restore contentView
BOOL hasContentView = [cell.subviews containsObject:cell.contentView];
if (!hasContentView)
[cell addSubview:cell.contentView];
// Configure cell
MyObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
if ([object.redColor isEqualToNumber:[NSNumber numberWithBool:YES]])
cell.colorView.backgroundColor = [UIColor redColor];
else
cell.colorView.backgroundColor = [UIColor clearColor];
return cell;
希望这会对某人有所帮助。
【讨论】:
这不是太耗费资源了吗?而且它不再“可重复使用”了? 我想知道这会有多贵。如果你计算量很大,你的 FPS 可能会显着下降,甚至低于 60。【参考方案2】:您可以使用此 tableview 委托方法来更改可见性(例如背景颜色)但不能更改数据:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
【讨论】:
我尝试在willDisplayCell
中设置颜色,但结果相同。它不会清除重用单元格的旧内容...
你可以尝试添加 [cell.contentView setNeedsDisplay];在返回单元格之前;
嗯,我试过打电话给[cell.contentView setNeedsDisplay];
,但还是不行……我也试过[cell.contentView layoutIfNeeded];
,但没有运气:(【参考方案3】:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
NSString *cellIdentifier = [NSString stringWithFormat:@"CustomCell %ld",(long)indexPath.row];
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell = nil;
if (cell == nil)
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
MyObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
if ([object.redColor isEqualToNumber:[NSNumber numberWithBool:YES]])
cell.colorView.backgroundColor = [UIColor redColor];
else
cell.colorView.backgroundColor = [UIColor clearColor];
return cell;
【讨论】:
你确定这是正确的代码吗??为什么要根据indexpath更改cellIdentifier??在 cell == nil 之前设置 cell = nil 也不起作用.....谢谢您的帮助... 我试过了,但由于 cellIdentifier 错误,导致应用程序崩溃。而且,如果我设置单元格 = nil,它会使所有单元格变为空白。 你好@TuğrulÖzdemir 请告诉我重用机制的正确方法。 实际上,并没有完全杀死 :) 为每一行使用不同的 cellIdentifier 会为每一行创建新的单元格。如果我有太多行会发生什么。我更喜欢对相似的行使用相同的标识符 单元格 = nil; if (cell == nil) 没有意义【参考方案4】:如果您想从重用单元列表中删除所有单元,请使用:
[tblView setValue:nil forKey:@"_reusableTableCells"]
如果您想从重复使用的单元格列表中删除单个单元格,请使用:
NSString* cellID = [NSString stringWithFormat:@"cellID%ld%ld",(long)indexPath.section,(long)indexPath.row];
NSMutableDictionary *temp1 = (NSMutableDictionary*)[tblView valueForKey:@"_reusableTableCells"];
[temp1 removeObjectForKey:cellID];
[tblView setValue:temp1 forKey:@"_reusableTableCells"];
其中 cellID 是在初始化单元时设置的唯一重用单元标识符。
【讨论】:
以上是关于UITableViewCell - 如何在重用之前重置内容的主要内容,如果未能解决你的问题,请参考以下文章
我的 UITableViewCell 正在重用以前的单元格 UIImage
iOS - 如何在不同的 UITableViewCell 中重用 UIView