iPhone - dequeueReusableCellWithIdentifier用法

Juk*_*rpa 61 iphone optimization objective-c uitableview

我正在开发一款iPhone应用程序,它有一个非常大的UITableView,其中包含从网络上获取的数据,因此我正在尝试优化其创建和使用.

我发现这dequeueReusableCellWithIdentifier非常有用,但是在看到很多使用它的源代码之后,我想知道我对这个函数的用法是不是很好.

这是人们通常做的事情:

UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];

if (cell == nil) {
  cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"Cell"];

// Add elements to the cell
return cell;
Run Code Online (Sandbox Code Playgroud)

这就是我做的方式:

// The cell row
NSString identifier = [NSString stringWithFormat:@"Cell %d", indexPath.row]; 

UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:identifier];

if (cell != nil)
  return cell;

cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:identifier];
// Add elements to the cell
return cell;
Run Code Online (Sandbox Code Playgroud)

不同之处在于人们对每个单元使用相同的标识符,因此只出列一个标识符可以避免分配新标识符.

对我来说,排队的重点是给每个单元格一个唯一的标识符,所以当应用程序要求它已经显示的单元格时,既不需要进行分配也不进行元素添加.

很好,我不知道哪个是最好的,"常用"方法将表的内存使用量提升到它显示的确切数量的单元格,而我使用的方法似乎有利于速度,因为它保留所有计算的单元格,但可能导致大内存消耗(除非队列有内部限制).

我这样用它错了吗?或者仅仅取决于开发人员,取决于他的需求?

pro*_*rmr 70

目的dequeueReusableCellWithIdentifier是使用更少的内存.如果屏幕可以容纳4或5个表格单元格,那么重复使用时,即使表格有1000个条目,也只需要在内存中分配4或5个表格单元格.

在第二种方式中没有重用.第二种方式没有优势,只使用一组表格单元格.如果您的表有1000个条目,那么您将在内存中分配1000个单元格.如果你打算这样做,你会把它们放在一个数组中,然后用行号索引数组并返回单元格.对于具有固定单元的小型表,这可能是一个合理的解决方案,对于动态或大型表,这不是一个好主意.

  • @manmal那也是关于记忆的.离开屏幕的细胞不会释放,而是重新用于可见的细胞. (5认同)
  • 这不完全正确.原因是UITableViewCell(及其所有子视图)的副本比它的全新实例更快.关于内存使用的部分由细胞在不再可见时释放的事实来处理.出列(=从模板对象复制)单元格只会加速单元格创建过程.因此,它不是关于内存,而是关于处理时间和使用的CPU资源(影响电池寿命等).您根本不保存任何实时内存空间 - 单元格仍然是单独的对象. (3认同)

Tim*_*Tim 19

至于单元标识符 - 您可以使用"类型标识符",而不是仅使用"单元格"作为标识符,而不是使用像OP这样的唯一标识符吗?例如,如果我的表有3种类型的单元格 - 一个具有非常复杂的子布局,一个单独使用Style1,一个单独使用Style2,我应该分别识别这三个单元格,然后在出列队列时重建它们nil.

例如:

-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath{
    NSString* ident = @"";
    if(indexPath.section == 0) ident= @"complicated";
    if(indexPath.section == 1) ident= @"style1";
    if(indexPath.section == 2) ident = @"style2";

    UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:ident];

    if(cell == nil){

       if(ident == @"complicated"){
          cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:ident] autorelease]; 
         // do excessive subview building
       }
       if(ident == @"style1"){
          cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyle1 reuseIdentifier:ident] autorelease]; 
       }

       if(ident == @"style2"){
          cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyle2 reuseIdentifier:ident] autorelease]; 
       }


    }
    if(ident == @"complicated"){
       // change the text/etc (unique values) of our many subviews
    }
    if(ident == @"style1"){
      [[cell textLabel] setText:@"Whatever"];
    }
    if(ident == @"style2"){
      [[cell textLabel] setText:@"Whateverelse"];
    }

    return cell; 
}
Run Code Online (Sandbox Code Playgroud)

(这段代码可能不会运行,因为我在这里写了它,但希望你能得到这个想法.)

如果他们想要所有标识符,我认为Apple不会用标识符创建整个可重用的单元格想法"cell",你不觉得吗?


Jef*_*eff 13

帮助我理解为什么惯用方法(你首先描述的方法)效果最好的文档是该方法的UITableViewCell类参考部分initWithStyle:reuseIdentifier:.

reuseIdentifier小节的内容如下:

您应该对同一表单的所有单元格使用相同的重用标识符.

"讨论"小节的内容如下:

重用标识符与具有相同通用配置,减去单元格内容的表视图的那些单元(行)相关联.

这些陈述清楚地告诉我说,惯用的方式来使用dequeueReusableCellWithIdentifier你的实现里面tableView:cellForRowAtIndexPath:为你UITableViewDataSource创建的每一块单元对象可见行可用行的总数无关.