TableView单元重用和不需要的检查标记 - 这让我感到害怕

nic*_*ick 11 reusability uitableview checkmark


Apple的iOS TableView和细胞重用正在扼杀我.我搜索,搜索和研究,但找不到好的文档或好的答案.问题是当TableView重新使用单元格时,在表格视图的下方单元格中重复设置在所选单元格上的Checkmarks(单元格附件)之类的内容.我知道细胞重用是由于内存限制而设计的,但是如果你有一个包含50个项目的列表,并且它开始在不需要它们的地方设置额外的复选标记,这使整个努力变得毫无用处.

我想要做的就是在我选择的单元格上设置复选标记.我已经尝试使用我自己的自定义单元类,以及由锅炉板TableView类生成的标准单元格,但它总是最终相同.

Apple甚至还有一个名为TouchCell的示例项目,您可以从开发中心下载,该项目应该显示使用左侧带有图像控件的自定义单元格设置复选标记的不同方式.该项目使用字典对象作为数据源而不是可静音数组,因此对于每个项目都有一个字符串值和bool检查值.此bool检查值应设置复选标记,以便它可以跟踪所选项目.只要使用15个以上的单元格填充TableView,此示例项目也会显示此愚蠢行为.单元格的重用开始设置不需要的复选标记.

我甚至尝试过为每个细胞使用一个真正独特的细胞标识符.因此,不是每个单元格都有@"Acell"之类的东西,我使用静态int,强制转换为字符串,以便细胞得到@"cell1",@"cell2"等.在测试期间,我可以看到数百个新细胞在哪里滚动期间生成,即使表只有30个项目.

它确实修复了复选标记重复问题,但我怀疑内存使用率过高.

当它们滚动回视图时,好像当前不在表的可视区域中的单元格会再次创建.

有没有人想出一个优雅的解决方案来解决这种恼人的行为?

Mar*_*ich 17

细胞重用可能很棘手,但你必须牢记两件事:

  • 对一种类型的单元使用一个标识符- 在一个表视图中使用不同的UITableViewCell子类时,实际上只需要使用多个标识符,并且必须依赖它们对不同单元的不同行为
  • 您重复使用的单元格可以处于任何状态,这意味着您必须再次配置单元格的每个方面 - 尤其是checkmars/images/text/accessoryViews/accessoryTypes等等

你需要做的是为你的复选标记状态创建一个存储 - 一个包含bools的简单数组(或者分别包含boolean NSNumber对象的NSArray)应该这样做.然后,当您必须使用以下逻辑创建/重用单元格时:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *reuseIdentifier = @"MyCellType";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
    if(cell == nil) {
        /* create cell here */
    }
    // Configure cell now
    cell.textLabel.text = @"Cell text"; // load from datasource
    if([[stateArray objectAtIndex:indexPath.row] boolValue]) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    } else {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }
    return cell;
}
Run Code Online (Sandbox Code Playgroud)

然后你将不得不对水龙头作出反应:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [stateArray replaceObjectAtIndex:indexPath.row withObject:[NSNumber numberWithBool:![[stateArray objectAtIndex:indexPath.row] boolValue]]];
    [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
Run Code Online (Sandbox Code Playgroud)

只记得NSMutableArray用于您的数据存储;)