UITableView dequeueReusableCellWithIdentifier Theory

时间:2010-08-23 22:57:58

标签: iphone uitableview reuseidentifier

当苹果为第一部iPhone开发UITableView时,他们在滚动浏览时会遇到性能问题。然后,一位聪明的工程师发现造成这种情况的原因是物品的分配带来了代价,因此他提出了一种重复使用细胞的方法。

  

“对象分配具有性能成本,特别是如果分配必须在短时间内重复发生 - 例如,当   用户滚动表格视图。如果您重复使用单元格而不是分配   新的,你大大提高了表视图的性能。“

     

来源:iOS参考资料库

要重复使用您使用的单元格:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

现在,我想知道的是,这里究竟发生了什么?如果有一个具有该标识符的单元格并且只返回那个标识符,它是否在TableView中查找?好吧,但是,如果它发送一个引用而不是分配,我有一个表视图,让我们说4个具有相同标识符的单元格都可见。如何在不分配的情况下将自身增加到四个实例中?

我想知道这一点,因为我正在构建一个日历类型组件,并且所有单元格只有更改中的文本具有相同的结构。所以,如果我能以某种方式重用我的细胞而不是分配,我想我可能会有更好的表现。

我自己的理论是它分配了四个单元格(仅仅因为它也有)。当一个单元格从屏幕上消失时,它将被放入TableView重用队列中。当需要一个新的单元时,它会在que中查找具有相同标识符的单元是否可用,它会在该单元上调用prepareForReuse方法并将其自身从队列中删除。

3 个答案:

答案 0 :(得分:43)

dequeueReusableCellWithIdentifier:只有在标记为可以重复使用的情况下才会返回cell。这就是为什么在几乎每种cellForRowAtIndexPath:方法中你都会看到像

这样的东西


UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (nil == cell) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                   reuseIdentifier:CellIdentifier];
}

// Do something to cell

return cell;

实际上,将分配足够的行来填充tableview的可见部分(加上一两个)。当屏幕显示cells scroll时,它们会从table中移除,并标记为reuse已准备就绪。随着“可用单元格”队列的增长,要求dequeued cell的行将开始获取要使用的cell,此时您将不再需要分配。

答案 1 :(得分:13)

deqeueueReusableCellsWithIdentifier:的代码如下所示:

(取自我自己的一个项目,其中我在分页滚动视图中执行与视图/页面类似的操作)

- (UIView*) dequeueReusablePage
{
    UIView* page = [reusablePages_ anyObject];
    if (page != nil) {
        [[page retain] autorelease];
        [reusablePages_ removeObject: page];
    }
    return page;
}

因此它保留了一个简单的NSMutableSet可重用对象。

当单元格滚动离开屏幕并且不再可见时,它们将被放入此集合中。

所以你从一个空集开始,只有当你真的有更多的数据显示然后在屏幕上可见时,该集才会增长。

使用过的单元格从屏幕顶部滚动,放入集合中,然后拍摄出现在屏幕底部的单元格。

答案 2 :(得分:2)

dequeueReusableCellWithIdentifier的目的是减少使用内存。如果我们在tableView中使用100个单元格,则每次需要创建100个单元格。它会减少应用程序功能并可能导致崩溃。 为dequeueReusableCellWithIdentifier初始化我们创建的特定数量的单元格,并且单元格将再次用于进一步处理。

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *TableIdentifier = @"YourCellIdentifier";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TableIdentifier];

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TableIdentifier];
    }

    ExternalClassTableViewCell *myCell = [[ExternalClassTableViewCell alloc]init];
    myCell.MyCellText.text = [tableData objectAtIndex:indexPath.row];
    myCell.MyCellImage.backgroundColor = [UIColor blueColor];

    return cell;
}