TableView 单元格重用和不需要的复选标记 - 这让我很伤心 [英] TableView Cell reuse and unwanted checkmarks - this is killing me

查看:25
本文介绍了TableView 单元格重用和不需要的复选标记 - 这让我很伤心的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


Apple 的 iOS TableView 和单元格重用让我很崩溃.我搜索、搜索和研究,但找不到好的文档或好的答案.问题在于,当 TableView 重用单元格时,在表视图中更下方的单元格中会重复设置在选定单元格上的复选标记(单元格附件).我知道由于内存限制,单元重用是设计使然,但是如果您有一个包含 50 个项目的列表,并且它开始在不需要的地方设置额外的复选标记,这将使整个努力变得毫无用处.


Apple's iOS TableView and cell reuse is killing me. I searched and searched and studied, but can't find good docs or good answers. The problem is that when the TableView reuses cells things like Checkmarks (cell accessory) set on a selected Cell are repeated in the cells further down in the table view. I understand that cell reuse is by design, due to memory constraints, but if you have a list with say 50 items, and it starts setting extra checkmarks where they're not wanted, this makes whole endeavor useless.

我想要做的就是在我选择的单元格上设置一个复选标记.我已经尝试过使用我自己的自定义单元格类和由样板 TableView 类生成的标准单元格,但结果总是一样的.

All I want to do is set a checkmark on a cell I've selected. I've tried this using my own custom cell class, and standard cells generated by a boiler plate TableView class, but it always ends up the same.

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

Apple even have an example project called TouchCell you can download from the dev center, that is supposed to show a different way of setting a checkmark using a custom cell with an image control on the left. The project uses a dictionary object for a data source instead of a muteable array, so for each item there is a string value and bool checked value. This bool checked value is supposed to set the checkmark so it can track selected items. This sample project also displays this goofy behavior as soon as you populate the TableView with 15+ cells. The reuse of cells starts setting unwanted check marks.

我什至尝试过为每个单元格使用真正唯一的单元格标识符.因此,不是每个单元格都有类似 @"Acell" 的东西,我使用了一个静态整数,转换为一个字符串,这样单元格就得到了 @"cell1"、@"cell2" 等.不过,在测试过程中,我可以看到数百个新单元格在哪里在滚动期间生成,即使表格只有 30 个项目.

I've even tried experimenting with using a truely unique Cell Identifier for each cell. So instead of each cell having something like @"Acell" I used a static int, cast to a string so the cells got @"cell1", @"cell2" etc. During testing though, I could see that hundreds of new cells where generated during scrolling, even if the table only had 30 items.

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

It did fix the checkmark repeat problem, but I suspect the memory usage was going way too high.

就好像当前不在表格可视区域中的单元格在滚动回视图时会重新创建.

It's as though the cells that are not currently in the viewable area of the table are created all over again when they are scrolled back into view.

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

Has anyone come up with an elegant solution to this irritating behavior?

推荐答案

单元格重用可能很棘手,但您必须牢记 2 件事:

cell reusing can be tricky but you have to keep 2 things in mind:

  • 为一种类型的单元格使用一个标识符 - 只有当您在一个表视图中使用不同的 UITableViewCell 子类时才需要使用多个标识符,并且您必须依赖它们对不同细胞的不同行为
  • 您重用的单元格可以处于任何状态,这意味着您必须再次配置单元格的各个方面 - 特别是检查标记/图像/文本/附件视图/附件类型等
  • Use one identifier for one type of cell - Using multiple identifiers is really only needed when you use different UITableViewCell-subclasses in one table view and you have to rely on their different behaviour for different cells
  • The cell you reuse can be in any state, which means you have to configure every aspect of the cell again - especially checkmars / images / text / accessoryViews / accessoryTypes and more

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

What you need to do is to create a storage for your checkmark states - a simple array containing bools (or NSArray containing boolean NSNumber objects respectively) should do it. Then when you have to create/reuse a cell use following logic:

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

那么你将不得不对点击做出反应:

then you will have to react on taps:

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

请记住将 NSMutableArray 用于您的数据存储;)

Just remember to use NSMutableArray for your data store ;)

这篇关于TableView 单元格重用和不需要的复选标记 - 这让我很伤心的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆