可重用的 TableView 标题视图

Posted

技术标签:

【中文标题】可重用的 TableView 标题视图【英文标题】:Reusable TableView header views 【发布时间】:2009-06-06 17:07:33 【问题描述】:

出于性能考虑,通常重用 UITableView 的单元格。 有没有办法对 TableView 标题的视图做同样的事情? 我说的是委托方法返回的那些:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

我尝试执行以下操作,但似乎没有按预期工作:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

    static NSString *CellIdentifier = @"Header";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
    if (cell == nil) 
        cell = [self getHeaderContentView: CellIdentifier];
    
    return cell;

有没有办法重用标题的视图?

【问题讨论】:

ios 6 开始,您现在拥有 UITableViewHeaderFooterView,它使用了重用标识符。 但目前您不能将 UITableViewHeaderFooterView 与 UI Builder 一起使用。 【参考方案1】:

Apple 内置重用 tableview 单元格的原因是因为虽然 tableview 可能有很多行,但只有少数几行显示在屏幕上。无需为每个单元分配内存,应用程序可以重用已经存在的单元并根据需要重新配置它们。

首先,标题视图只是 UIView,虽然 UITableViewCell 是 UIView 的子类,但它们并不打算作为节标题的视图。

此外,由于节标题通常比总行少得多,因此没有理由构建可重用性机制,事实上 Apple 还没有为通用 UIView 实现这一机制。

请注意,如果您只是为标题设置标签,则可以改用-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section

对于更自定义的东西,例如带有红色文本的标签(或按钮、图像等),您可以执行以下操作:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 
  UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0,0, 320, 44)] autorelease];
  UILabel *label = [[[UILabel alloc] initWithFrame:headerView.frame] autorelease];
  label.textColor = [UIColor redColor];
  label.text = [NSString stringWithFormat:@"Section %i", section];

  [headerView addSubview:label];
  return headerView;

【讨论】:

我认为标签不应该是自动释放,而是在添加到 headerView 后释放。你有什么想法? “几乎没有理由建立可重用性机制......” Martins 的评论通常是正确的,但并不完全正确。对于任何试图达到 60fps(如我)的人来说,带有自定义视图的 viewForHeaderInSection 是魔鬼。为每个标题启动一个新视图,特别是如果您的组不大,实际上将无法达到上述性能,因为它通常会花费我 5 FPS。如果您可以在设计中避免使用自定义标头,它将给您带来性能提升。 但是如果您真的需要使用自定义标题视图,那么将 FPS 保持在 60 的最佳方法是什么? 虽然你的解释很透彻,但这确实不能回答问题。 从 iOS 6 开始我们也应该重用这些:UITableViewHeaderFooterView【参考方案2】:

您可以通过创建 UITableViewHeaderFooterView 类来实现它 它是 UIView 的子类 您还需要创建一个单独的 XIB,因为它不会通过 UITableViewHeaderFooterView 创建自动创建。

用tableview注册Nib

[self.tblCart registerNib:[UINib nibWithNibName:@"CartHeaderView" bundle:nil] forHeaderFooterViewReuseIdentifier:@"CartHeader"];

现在您可以在 viewForHeaderInSection

中访问它
-(UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section


    CartHeaderView *sectionHeader=[tableView dequeueReusableHeaderFooterViewWithIdentifier:@"CartHeader"];
 return sectionHeader;

注意: 要设置背景颜色,您需要创建一个与节标题具有相同框架的子视图并为该视图设置颜色。

你可以关注

Changing the background color on a UITableViewHeaderFooterView loaded from a xib says to use contentView.backgroundColor instead

【讨论】:

【参考方案3】:

一个简单而有效的解决方案:

@interface SectionedTableViewController ()
    @property (nonatomic, strong) UINib*          sectionHeaderNib;
    @property (nonatomic, strong) NSMutableArray* sectionHeaders;
@end

@implementation SectionedTableViewController

@synthesize sectionHeaderNib = sectionHeaderNib_;
@synthesize sectionHeaders = sectionHeaders_;

- (void) viewDidUnload

    self.sectionHeaders = nil;
    [super viewDidUnload];


- (NSMutableArray*) sectionHeaders

    if (!sectionHeaders_)
        self.sectionHeaders = [NSMutableArray array];
    return sectionHeaders_;



- (UINib*) sectionHeaderNib

    if (!sectionHeaderNib_)
        self.sectionHeaderNib = [UINib nibWithNibName: NSStringFromClass(YourHeaderView.class) bundle: nil];
    return sectionHeaderNib_;



- (YourHeaderView*) dequeueHeader

    return [self.sectionHeaders firstObjectPassingTest: ^(id obj)  return (BOOL) ([obj superview] == nil); ];



- (NSString*) sectionHeaderTitleForSection: (NSInteger) section

    return nil;



- (UIView*) tableView: (UITableView*) tableView viewForHeaderInSection: (NSInteger) section

    YourHeaderView* headerView = [self dequeueHeader];
    if (!headerView)
    
        headerView = [YourHeaderView instanceFromNib: self.sectionHeaderNib];
        [self.sectionHeaders addObject: headerView];
    
    return headerView;


@end

【讨论】:

这是什么:firstObjectPassingTest?

以上是关于可重用的 TableView 标题视图的主要内容,如果未能解决你的问题,请参考以下文章

由于可重用性问题,tableview 单元格上的图像重复

为不同的表视图创建可重用的页脚视图(Swift 5)

UITableView 可重用的自定义单元格在子视图中显示错误的内容

Tableview,如何禁用可重用单元? (用于测试目的)

如何在可重用的 tableView 单元格中更新 UITextfield 中的文本值,每个单元格中的值不同

在这种情况下,如何使用自定义 tableView 单元格处理可重用单元格(从代码中的其他位置更改单元格背景颜色不起作用)