【问题标题】:How to avoid the repaint effect when using the UITableView?使用 UITableView 时如何避免重绘效果?
【发布时间】:2011-02-11 00:06:37
【问题描述】:

我最近调试了一个视图控制器的问题,并注意到每次我向上或向下拖动视图时,它都会重新绘制我的 UITableView 的全部内容(因为它每次都会调用 cellForRowAtIndexPath 方法)。是否可以使用内存数据源或向我的视图控制器添加另一个委托,这样它就不会每次都重新绘制?

当用户与单元格交互时,我不会修改单元格内的任何内容,因此在调用初始“viewDidLoad”后,我的数据源将是静态的。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

  if ([self.hats count] > 0) {
    //do some complex stuff in here that hurts each time we re-draw this ...
  }

    return cell;  
}

提前谢谢你

【问题讨论】:

  • 贴出复杂东西的代码。不保存单元格。一旦它们离开屏幕,它们就会进入再利用箱,当它们变得可见时,它们必须被重新绘制。
  • 我没有完整的 src 但基本上我创建了一个 UIView 并将其添加到单元格的子视图中。但在这一步之前,我向 UIView(动态)添加了一些其他控件,然后将它们全部释放。重新加载这些只是感觉很痛苦。认为这样的静态数据源可能存在委托或技术以避免性能命中
  • 你看,这就是问题所在。所有添加内容的子视图都进入 if (cell == nil) { // here }。如果操作正确,您可以添加数十个视图而不会影响性能
  • 我想说应该进入 if (cell==nil)...

标签: objective-c uitableview


【解决方案1】:

所以// complex stuff 表示添加 UIViews。

我为 UIImageView 做了一个例子。由于您不展示复杂的东西,因此您必须自己采用它。

您的代码如下所示:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    if ([self.hats count] > 0) {
        UIImageView *imageView = [[UIImageView....];
        [cell.contentView addSubView:imageView];
        [imageView setImage:foo];
        [imageView release];
    }
    return cell;
}

重构您的代码,使其看起来像这样:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        UIImageView *imageView = [[UIImageView....];
        [cell.contentView addSubView:imageView];
        imageView.tag = 42;
        [imageView release];
    }

    if ([self.hats count] > 0) {
        UIImageView *imageView = [cell viewWithTag:42];
        [imageView setImage:foo];
    }
    return cell;
}

等等,你的 tableview 是响应式的。因为您为每个单元格创建了一次子视图。当单元格不再使用并进入重用箱时,子视图将保留在其中。

如果您在一个单元格中需要 4 个图像视图,而在另一个单元格中需要 8 个图像视图,则在创建单元格时添加 8 个图像视图,并为它们提供一个 CGRectZero 框架,当然每个视图都有一个不同的标签。
如果您需要它们,则显示它们,如果您不需要它们,则将图像设置为零并将帧设置为零。

【讨论】:

  • 每次移动视图时,我为什么要进入第一个 if 语句?单元格不应该已经有你提到的值并在初始设置后跳过这个吗?
  • 而不是使用这一行“UITableViewCell cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];”我应该改用这个吗? "UITableViewCell *cell = (UITableViewCell)[tableView cellForRowAtIndexPath:indexPath];"
  • @Toran Billups 如果您使用自定义单元格(即从笔尖加载),请确保设置正确的单元格标识符。当一个单元格不会被重用时,很可能是因为创建的单元格的重用标识符和用于出队的标识符不匹配。
  • 我实际上并没有加载“自定义”单元格,除非这意味着只有一个带有单个 UITableView 的 XIB。另外,我如何确定 CellIdentifier 应该是什么才能在此处重用?我可以 NSLog 一些东西来开始吗?感谢大家的帮助!
  • 或者我是否需要在 Interface Builder 中为 UITableView 本身设置 Identifier 字段?不确定这是否存在没有定义的自定义单元格(因为我只有一个 UITableView - 不是自定义单元格)
猜你喜欢
  • 2021-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多