34

当苹果UITableView为第一款 iPhone 开发时,他们在滚动浏览它时遇到了性能问题。然后一位聪明的工程师发现,造成这种情况的原因是对象的分配是有代价的,所以他想出了一种重用单元的方法。

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

来源:iOS 参考库

要重用您使用的单元格:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

现在,我想知道的是,这里实际发生了什么?如果有一个具有该标识符的单元格并仅返回该标识符,它是否会在 TableView 中查找?好吧,是的,但是如果它发送引用而不是分配,并且我有一个表格视图,假设具有相同标识符的 4 个单元格都可见。它如何在不分配的情况下将自己乘以四个实例?

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

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

4

3 回答 3

44

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。随着“可用单元”队列的增长,您请求 a 的dequeued cell行将开始获取cell要使用的 a,此时您将不必再分配。

于 2010-08-23T23:04:16.703 回答
13

的代码deqeueueReusableCellsWithIdentifier:将如下所示:

(取自我自己的一个项目,我在分页滚动视图中对视图/页面做了类似的事情)

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

所以它使用可重用的对象保持简单NSMutableSet

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

因此,您从一个空集开始,只有当您实际上有更多数据要显示然后在屏幕上可见时,该集才会增长。

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

于 2010-08-23T23:15:16.797 回答
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;
}
于 2016-09-07T09:55:25.187 回答