【问题标题】:UITableView dequeueReusableCellWithIdentifier TheoryUITableView dequeueReusableCellWithIdentifier 理论
【发布时间】:2010-08-23 22:57:57
【问题描述】:

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

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

来源:iOS 参考库

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

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

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

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

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

【问题讨论】:

  • 简短回答:是的。它有一个单独的重用队列/集,与表中已有的东西不同。

标签: iphone uitableview reuseidentifier


【解决方案1】:

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 以使用,此时您将不必再分配。

【讨论】:

  • “一两个以上”部分不正确。它准确地分配了需要的东西。试试这个,你会看到。
  • 确实像 St3fan 说的,如果你 NSLog 请求单元格的方法,你会看到它只请求需要的单元格。
  • 我解释的时候可能有点草率。 “需要什么”因情况而异。当你开始滚动 UITableView 时,更多的因素开始发挥作用。一个例子:如果你快速滚动一个长表格视图,当没有可用的单元格出列时,可能会导致表格请求一个单元格。
  • 在“[UITableViewCell alloc]”之前有一个多余的“[”。
  • 新实现的dequeue 方法保证返回一个单元格。我认为这个答案需要更新。
【解决方案2】:

deqeueueReusableCellsWithIdentifier: 的代码如下所示:

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

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

所以它保留了一个简单的NSMutableSet 和可重用的对象。

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

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-14
      • 1970-01-01
      • 2014-11-07
      • 2013-08-19
      • 2016-06-29
      相关资源
      最近更新 更多