带IB的UITableViewHeaderFooterView

28
多年来,我一直避免使用Interface Builder。但最近我决定给它一个机会。这并不容易。
以UITableViewHeaderFooterView为例,就像UITableViewCell一样,它有一个contentView属性。但不同的是,Interface Builder对象库中没有它的模板。
那么,我们该如何使用Interface Builder创建一个UITableViewHeaderFooterView,并将内容放在contentView中呢?registerNib:forHeaderFooterViewReuseIdentifier:的存在让我认为这应该是可能的。
9个回答

32

这是我能做到的最接近通过IB定义UITableViewHeaderFooterView的方法:

a. 创建一个UITableViewHeaderFooterView子类(MYTableViewHeaderFooterView)。

b. 仅为contentView创建一个nib文件(MYTableViewHeaderFooterContentView)。

c. 在MYTableViewHeaderFooterView中重写initWithReuseIdentifier:方法,以加载在nib文件中定义的视图。

 - (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithReuseIdentifier:reuseIdentifier];
    if (self)
    {
        NSArray* objects = [[NSBundle mainBundle] loadNibNamed:@"MYTableViewHeaderFooterView"
                                                          owner:self
                                                        options:nil];
        UIView *nibView = [objects firstObject];
        UIView *contentView = self.contentView;
        CGSize contentViewSize = contentView.frame.size;
        nibView.frame = CGRectMake(0, 0, contentViewSize.width, contentViewSize.height);
        [contentView addSubview:nibView];
    }
    return self;
}

d. 注册MYTableViewHeaderFooterView类,而不是Nib文件:

[self.tableView registerClass:[MYTableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:@"cell"];

contentViewSize 是 {0,0,0,0}。 - john07
6
苹果已经提供了一些示例代码来证明这实际上是不必要的。这是一个针对新手的问题链接:https://dev59.com/qGMm5IYBdhLWcg3wZ-MX#20073742。 - Daniel Galasko
过去的回忆 - 你可以使用contentView.bounds代替CGRectMake,尽管@DanielGalasko的答案是完全正确的。 - epolyakov

25

我刚用底部视图和NIB文件完成了以下操作:

  1. 创建一个名为 CustomFooterView.xib 的空NIB文件。
  2. 在Interface Builder中编辑NIB文件,并将最上层的UIView自定义类更改为UITableViewHeaderFooterView。
  3. 在NIB中禁用自动布局
  4. UITableViewHeaderFooterView视图的背景颜色设置为默认
  5. 使视图自由形式并更正大小(例如320 x 44)。
  6. 在UITableViewController的viewDidLoad中注册要使用的带有复用标识符的NIB文件:

[self.tableView registerNib:[UINib nibWithNibName:@"CustomFooterView" bundle:nil] forHeaderFooterViewReuseIdentifier:@"Footer"];
在您的UITableViewController的tableView:viewForFooterInSection:中使用Footer标识符来获取并返回视图:
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
    if (section == 2)
        return [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"Footer"];

    return nil; 
}

3
虽然我需要做两件事才能让它正常工作,但它的表现很好:1. 禁用 NIB 的自动布局。2. 在 NIB 中将 UITableViewHeaderFooterView 视图的背景颜色设置为“默认”。 - Frederik
谢谢@Frederik,我根据那个更新了答案。 - Markus Rautopuro
1
我认为这是更好的解决方案,因为你可以在这个xib中连接插座,而在另一个解决方案中则不行。 - JonEasy
这对我来说是一个更加干净的解决方案。 - C. Bess
1
这个解决方案非常成功,而且比使用tableview cell作为标题更清晰。 - Vineeth Joseph

14

只需在IB中使用UITableViewCell模板。将类更改为UITableViewHeaderFooterView。这样您就可以得到一个带有contentView的表头或表尾视图。


1
这是最佳解决方案! - user3378170
我不知道这是否是“这是最好的解决方案!”但它运行良好且易于实现!谢谢 - Guilherme

7
我找到了更简单的方法。
1)创建UITableViewCell子类并设置您的xib文件。
2)在头文件中将超类从UITableViewCell更改为UITableViewHeaderFooterView。
就是这样。

5
至少在XCode 6.4上,这似乎无法使用。当您尝试在IB中更改类时,它不会完成(这表明事情出了问题)。如果您点击其他地方并返回,它会恢复为“UITableViewCell”。如果查看Nib的对象列表,则会显示一个“UITableViewCell”。当您尝试进行加载时,在头部被取消排队时会触发断言,指出它是错误的类型:“'invalid nib registered for identifier (sectionHeader) - nib must contain exactly one top level object which must be a UITableViewHeaderFooterView instance'” - Benjohn

6
这个解决方案非常实用,特别是当你想要正确处理iOS 9中引入的易读内容指南时。它不是创建一个UITableViewHeaderFooterView,而是在需要时返回一个自定义的UIView(来自XIB):
  1. Create a new class that subclasses UIView ("AwesomeHeaderView") and create your outlets:

    class AwesomeHeaderView: UIView {
        @IBOutlet var myCustomLabel: UILabel!
    }
    
  2. Create a XIB file ("MyNewHeader.xib") with a UIView as the parent view. Change the parent UIView's class type to your newly created custom class ("AwesomeHeaderView"). As required, add any additional views as it's children and link outlets etc. (NB: To ensure views comply to the new Readable Content Guides I check the boxes "Preserve Superview Margins" and "Follow Readable Width" on all objects).
  3. In your UIViewController (or UITableViewController) call the following:

    func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        guard let headerView = NSBundle.mainBundle().loadNibNamed("MyNewHeader", owner: nil, options: nil).first as? AwesomeHeaderView else {
            return nil
        }
    
        // configure header as normal
        headerView.backgroundColor = UIColor.redColor()
        headerView.myCustomLabel.textColor = UIColor.whiteColor()
        headerView.myCustomLabel.text = "Hello"
    
        return header
    }
    

1
我也遇到了上述的弃用警告和无法设置背景颜色等问题。最终,我发现根据苹果的文档,

在大多数情况下,您可以直接使用[UITableViewHeaderFooter]类而无需子类化。如果您有自定义内容要显示,请为其创建子视图并将其添加到contentView属性中。

按照这个建议,我采取了以下步骤:

  1. I created a xib with a view that extends only UIView--not UITableViewHeaderFooter.
  2. In viewDidLoad I registered the built-in UITableViewHeaderFooter class

    tableView.registerClass(UITableViewHeaderFooterView.self, forHeaderFooterViewReuseIdentifier: "sectionHeader")

  3. In the viewForHeaderInSection delegate of my UITableViewController, I dequeued the header view by that identifier and checked to see if the header view already contained a subview. If not, I load my xib and add it. Then I set my text as needed.

    override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let header = self.tableView.dequeueReusableHeaderFooterViewWithIdentifier("sectionHeader")!
    
    if header.contentView.subviews.count == 0 { header.contentView.addSubview(loadMyNib()) }
    
    let myView = header.contentView.subviews[0] as! MyView
    myView.label.text = "..."
    
这似乎可行,利用复用,并且不会产生任何警告。

https://developer.apple.com/library/prerelease/tvos/documentation/UIKit/Reference/UITableViewHeaderFooterView_class/index.html#//apple_ref/occ/instm/UITableViewHeaderFooterView/prepareForReuse


1
以下解决方法使我能够将IB项目作为变量拖动分配到代码中。UITableViewHeaderFooterView默认情况下不允许这样做。
1.创建一个(New File/CocoaTouchClass)UITableViewHeaderFooterView .h.m.xib通常。
2.临时将超类从UITableViewHeaderFooterView重命名为UIView。根据需要将UI项目拖动分配到代码中,IB将正确地分配键值,完成后恢复为UITableViewHeaderFooterView。
3.在您的tableview中,使用registerNib:进行注册,而不是registerClass:。其余部分准备正常(即:dequeue)。

0
我发现的一个可怕的黑客方法是在你的headerFooter类中创建一个IBOutlet contentView,并将其连接到xib中的“content view”(让你的xib像tableViewCell一样布局,View->contentView->mystuff)。
你会收到警告,准备好使用黑客方法...
删除IBOutlet,它就可以正常工作了。

0

我找到的最好方法:

  1. 创建您的HeaderFooterView(.h/.m),如header
  2. 创建一个xib(view),并命名相同名称
  3. 将根视图类设置为您的类(header)
  4. [重要] 将所有outlets连接到根视图,而不是File's Owner

最后,将您的nib注册到table中(完成)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接