Reputation: 120324
After many years of avoiding Interface Builder like the plague I decided to give it a chance. It's not easy.
Take UITableViewHeaderFooterView
for example. Like UITableViewCell
, it has a contentView
property. Unlike UITableViewCell
, it doesn't have a template in the Interface Builder object library.
How are we supposed to use Interface Builder to create a UITableViewHeaderFooterView
with the content inside contentView
? The fact that registerNib:forHeaderFooterViewReuseIdentifier:
exists makes me think this should be possible somehow.
Upvotes: 28
Views: 27783
Reputation: 4181
The best way I found:
header
header
)File's Owner
Last, register your nib to table(All done).
Upvotes: 0
Reputation: 1700
Following workarounds enable me to drag-assign IB items to code as variables. UITableViewHeaderFooterView doesnt allow that out of the box.
create a (New File/CocoaTouchClass) UITableViewHeaderFooterView .h.m.xib normally
temporarily rename superclass from UITableViewHeaderFooterView to UIView. Drag-assign your UI items to code as needed, IB will assign key-value correctly, revert back to UITableViewHeaderFooterView when done.
Upvotes: 1
Reputation: 2080
This solution works well, especially if you want it to work correctly in relation to Readable Content Guides (introduced in iOS 9). Instead of creating a UITableViewHeaderFooterView, it simply returns a custom UIView (from a XIB) when it is required:
Create a new class that subclasses UIView ("AwesomeHeaderView") and create your outlets:
class AwesomeHeaderView: UIView {
@IBOutlet var myCustomLabel: UILabel!
}
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
}
Upvotes: 6
Reputation: 543
I also experienced the deprecation warning above and an inability to set background color, etc.. Eventually, I found that according to Apple's documentation,
You can use [the UITableViewHeaderFooter] class as-is without subclassing in most cases. If you have custom content to display, create the subviews for your content and add them to the view in the contentView property.
Following that suggestion, I took these steps:
In viewDidLoad I registered the built-in UITableViewHeaderFooter class
tableView.registerClass(UITableViewHeaderFooterView.self, forHeaderFooterViewReuseIdentifier: "sectionHeader")
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 = "..."
This seems to work, leverages reuse, and does not produce any warnings.
Upvotes: 1
Reputation: 1526
An awful hack I figured out is to create a IBOutlet contentView ih your headerFooter class and hook it up to the your "content view" in the xib (Have your xib laid out like a tableViewCell, View->contentView->mystuff).
You'll get warnings, ok ready for the hack...
Delete the IBOutlet and it will all work.
Upvotes: 0
Reputation: 120324
This is the closest I got to define a UITableViewHeaderFooterView
with IB:
a. Create a UITableViewHeaderFooterView
subclass (MYTableViewHeaderFooterView
).
b. Create a nib file for the contentView
only (MYTableViewHeaderFooterContentView
).
c. Override initWithReuseIdentifier:
in MYTableViewHeaderFooterView
to load the view defined in the nib file.
- (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. Register the MYTableViewHeaderFooterView
class instead of the nib file:
[self.tableView registerClass:[MYTableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:@"cell"];
Upvotes: 32
Reputation: 570
Just use the UITableViewCell template in IB. Change the class to UITableViewHeaderFooterView. Here you have it... with a contentView.
Upvotes: 14
Reputation: 1531
I found easier way.
1) Create subclass of UITableViewCell and set your xib file
2) In your header file change superclass from UITableViewCell to UITableViewHeaderFooterView
That's it.
Upvotes: 7
Reputation: 8365
I just did this with a footer and a NIB file:
UITableViewHeaderFooterView
view to Default.In your UITableViewController viewDidLoad
register the NIB file to be used with a reuse identifier:
[self.tableView registerNib:[UINib nibWithNibName:@"CustomFooterView" bundle:nil] forHeaderFooterViewReuseIdentifier:@"Footer"];
In your UITableViewController's tableView:viewForFooterInSection:
use the Footer identifier to fetch and return the view:
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
if (section == 2)
return [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"Footer"];
return nil;
}
Upvotes: 25