iPhone – dequeueReusableCellWithIdentifier用法

我正在从事一个iPhone应用程序,它有一个相当大的UITableView与从networking采集的数据,所以我试图优化其创build和使用。

我发现dequeueReusableCellWithIdentifier是相当有用的,但在看到许多使用这个源代码后,我想知道如果我使用这个函数是好的。

以下是人们通常做的事情:

UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"Cell"]; // Add elements to the cell return cell; 

我这样做是这样的:

 // 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; 

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

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

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

我错用这种方式吗? 还是取决于他的需求,是否取决于开发者?

dequeueReusableCellWithIdentifier的用途是使用较less的内存。 如果屏幕可以放置4或5个表格单元格,那么即使表格有1000个条目,只需要在内存中分配4或5个表格单元格即可。

第二种方式没有重用。 第二种方法比使用表格单元格arrays没有什么优势。 如果你的表有1000个条目,那么你将在内存中分配1000个单元。 如果你打算这么做的话,你可以把它们放在一个数组中,然后用行号索引数组,然后返回单元格。 对于固定单元格的小型表格,这可能是一个合理的解决scheme,对于dynamic或大型表格,这不是一个好主意。

至于单元格标识符 – 而不是仅仅使用“单元格”作为标识符,而不是像OP一样使用唯一的标识符,你能使用“types标识符”吗? 例如,如果我的表有三种types的单元格,一种是非常复杂的子布局,一种是Style1 ,另一种是Style2 ,那么我应该单独标识这三种Style2 ,然后在出现零时才重build它们。

例如:

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

(这段代码可能不会运行,因为我写在这里,但希望你能明白这一点。)

我不认为如果苹果公司希望所有的标识符都是"cell" ,就不会用标识符来创build整个可重用的单元格思路,你不觉得吗?

帮助我理解为什么惯用方式(您首先描述的方法)效果最好的文档是initWithStyle:reuseIdentifier:方法中的UITableViewCell类引用部分。

重新使用reuseIdentifier子部分读取:

您应该为同一表单的所有单元使用相同的重用标识符。

“讨论”小节写道:

重用标识符与具有相同一般configuration的表视图的那些单元(行)相关联,减去单元格内容。

这些语句使我清楚,在您的UITableViewDataSourcetableView:cellForRowAtIndexPath:实现中使用dequeueReusableCellWithIdentifier的惯用方式为每个可见行创build一个单元对象,而不pipe可用的总行数。

我认为第一个是最好的(和你说的常见)的方式来实现一个UITableView 。 用第二种方法,将为每个显示的新单元分配内存,并且不会重用内存。

UITableView内部使用一个带有标识符的单元格作为“模板”。 所以下一次(以表格的forms阅读的时候)尝试使用deque,它只是创build一个新的单元格,但是使用存储的对象作为模板。 因此,您仍然需要更新其用户界面以反映上下文中的单元格内容。

这也意味着UITableView正在为我们自己做单元的内存pipe理。 从理论上讲,只有可见单元的UITableViewCell对象UITableViewCell太多了。 但实际上,可能还有一些等待被释放的内存。

这基本上可以节省大量的时间,特别是在有1000个单元的情况下。

在任何内存溢价的便携式设备上,我们都应该把内存的分配推迟到最后一刻,并在其工作完成的时候释放内存。 dequeAndReusing一个单元格实现这一点,做得很好。

另一方面,如果你的单元格是一个自定义的单元格,那么我们可能最有可能加载一个笔尖并从中提取。 如果是这样的话,你可以使用一个标识符来取消或者你可以从nib中加载它。 程序没有区别。

唯一的区别可能是在加载时间。 允许使用标识符单元格作为模板来创build一个新的单元格的视图可能比从nib的加载稍快,但是它几乎不可见,并且取决于上下文。

要区分单元格与其他单元格,您可以使用单元格的标签属性,或者如果您正在使用自定义单元格,那么通过将子类化UITableViewCell任何新属性引入到自定义单元格非常容易。

即使所有这些你被卡住,仍然需要获得细胞,那么你可以尝试下面的代码

UITableViewCell *cell = [self cellForRowAtIndexPath:indexPath]

而应尽可能地避免,因为它会生成单元格的副本,但不会返回现有的单元格,而内​​容将具有相同的值。