Iphone 在UITableView中滚动后项目混淆

Iphone 在UITableView中滚动后项目混淆,iphone,cocoa-touch,Iphone,Cocoa Touch,当我在UITableView中滚动时,单元格会混淆。 我做错了什么 这是我的方法: - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableC

当我在UITableView中滚动时,单元格会混淆。 我做错了什么

这是我的方法:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
    [cell insertSubview:[itemArray objectAtIndex:indexPath.row] atIndex:indexPath.row]; 
    return cell;
}
更新


它现在通过使用cell.contentView工作,但现在当我选择一个项目时,所选项目与另一个单元格的内容重叠…

我认为您的问题在于,您将行逻辑应用于单元格内的视图层次结构,而不是单元格本身

这一行:

[cell insertSubview:[itemArray objectAtIndex:indexPath.row] atIndex:indexPath.row];
从数组中获取视图,并将其添加到单元格现有子视图堆栈的特定index.row处的单元格子视图中。它不会确保将正确的视图插入到正确的单元格中。如果您从未从上一次迭代中删除视图,那么您将看到所有这些视图都堆积在单独的重用单元中

至少,在添加最多的单元子视图之前,需要删除以前添加的所有单元子视图。您还应该只向单元格的
contentView
视图添加子视图,而不向单元格本身添加子视图

因此:


TechZen在这里的建议是正确的。从代码中可以清楚地看出,您误解了insertSubview:atIndex。我想您可能还需要更好地了解tableView:CellForRowatineXpath:何时调用和何时不调用

不幸的是,您从sagar这里得到了一些不好的建议,这可能会让您更加困惑,特别是因为它可能在一开始看起来是有效的,但它会破坏您的滚动性能和内存使用。为了他的利益和你们的利益,让我尝试澄清tableView:cellforrowatinexpath:和重用标识符的概念

理解tableView:cellForRowAtIndexPath:和重用标识符的关键是理解构建UITableViewCell的成本很高。考虑所有你需要做的事情:

  • 分配一个单元格
  • 分配单元格的子视图
  • 定义单元内子视图的布局
  • 将子视图添加到单元中
  • 配置子视图的属性,如字体大小、颜色、文本换行、大小调整行为等
  • 配置单元的属性,如附件图像等
  • 定义要单元格显示的特定文本和/或图像
  • 创建表时,我们通常希望单元格具有相同的基本配置。它们通常具有相同数量的子视图、相同的位置、使用相同的字体等。事实上,每个单元格之间通常唯一需要改变的是上面列表中的第7项,即单元格显示的文本和图像

    第1步到第6步非常昂贵(特别是内存分配),因此如果我们对创建的每个单元格都执行这些步骤,只会在该单元格滚动到屏幕外时将其扔掉,这将扼杀我们的滚动性能。如果我们可以在单元格从屏幕上滚动下来时保存它,然后调整它的内容并将其重新用于我们需要显示的下一个单元格,那就更好了

    苹果认识到这种单元重用优化的必要性,因此他们在UITableView中构建了一种机制。当单元格从屏幕上滚动时,UITableView不会将其丢弃。相反,它查看单元格的重用标识符字符串,并将单元格放入与该标识符关联的特殊缓冲区中。下次调用dequeueReusableCellWithIdentifier时:使用相同的标识符,UITableView将从缓冲区中取出单元格并将其返回给您以供重用。这个单元格仍然有所有相同的子视图,配置与以前相同,所以您只需执行列表中的步骤7。只需更新单元格的文本和/或图像,就可以开始了

    正确使用此机制后,将只为每个可见行分配一个单元格,再为缓冲区分配一个单元格。无论您的表中有多少行,您的内存使用率都将保持较低,并且您的滚动将像黄油一样平滑

    Sagar建议您为每一行使用不同的重用标识符。希望你能明白为什么这是个坏主意。当每个单元格滚动出屏幕时,表视图将查看单元格的标识符,查看其唯一性,并为该特定行创建一个新的缓冲区。如果滚动10000行,表视图将以10000个缓冲区结束,每个缓冲区专用于一个单元格。当你创建10000个单元格对象时,你的滚动速度会不必要地慢,而且你的应用程序可能会在你到达表格底部之前耗尽内存

    因此,请继续并保留您的通用单元标识符。在
    if(cell==nil){}
    块中,放置所有单元格通用的所有设置代码。在该块下面,只放置填充每行唯一内容的代码。要访问每行内容都要更改的自定义子视图,可以使用-[UIView viewWithTag:],或者更好的方法是创建UITableViewCell的子类,并将自定义子视图作为子类的属性公开

    [[cell.contentView.subviews objectAtIndex:0] removeFromSuperview];
    [cell.contentView addSubview:[itemArray objectAtIndex:indexPath.row]];