Setting label in UITableView tableFooterView - auto-start
When my table view is empty, I want to add a simple label to the table footer to display the "no content" message. It worked great when I was setting the UILabel and UIView frameworks that I used for footerView, but now I am trying to convert them to use auto-layout and I cannot get it to work.
That's what I'm doing:
// Create the footer
UIView *tempFooter = [[UIView alloc] init];
UILabel *atext = [[UILabel alloc] init];
tempFooter.translatesAutoresizingMaskIntoConstraints = NO;
atext.translatesAutoresizingMaskIntoConstraints = NO;
atext.numberOfLines = 0;
[atext setText:@"Add Some Text"];
atext.textAlignment = NSTextAlignmentCenter;
atext.font = [UIFont italicSystemFontOfSize:14];
atext.textColor = [UIColor grayColor];
atext.backgroundColor = [UIColor clearColor];
atext.lineBreakMode = NSLineBreakByWordWrapping;
// add label to footer view, and add constraints
[tempFooter addSubview:atext];
NSLayoutConstraint *tvatt1 = [NSLayoutConstraint constraintWithItem:tempFooter
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:atext attribute:NSLayoutAttributeLeft
multiplier:1.0
constant:10.0];
NSLayoutConstraint *tvatt2 = [NSLayoutConstraint constraintWithItem:tempFooter
attribute:NSLayoutAttributeRight
relatedBy:NSLayoutRelationEqual
toItem:atext
attribute:NSLayoutAttributeRight
multiplier:1.0
constant:10.0];
NSLayoutConstraint *tvatt3 = [NSLayoutConstraint constraintWithItem:tempFooter
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:atext
attribute:NSLayoutAttributeTop
multiplier:5.0
constant:0];
NSLayoutConstraint *tvatt4 = [NSLayoutConstraint constraintWithItem:tempFooter
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:atext
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant: 0];
[tempFooter addConstraints: @[tvatt1, tvatt2, tvatt3, tvatt4]];
// set the footerview
self.tview.tableFooterView = tempFooter;
When I run this I get a crash:
2014-09-08 19: 57: 16.594 SimpleList [49442: 60b] * Assertion error in - [UITableView layoutSublayersOfLayer:], / SourceCache / UIKit_Sim / UIKit-2935.137 / UIView.m: 8794 2014-09-08 19: 57: 21.073 SimpleList [49442: 60b] * Application terminated due to non-display exception "NSInternalInconsistencyException", reason: "Auto layout is still required after executing -layoutSubviews. UITableView's implementation of -layoutSubviews requires calling super
I'm not sure what I am doing wrong. I also tried setting limits self.tview.tableFooterView
on the tempFooter
(fix against all 4 sides), but that doesn't change the crash. I also call:
[self.tview.tableFooterView layoutSubviews];
but that doesn't help either.
Any ideas what I am doing wrong?
source to share
You shouldn't set translatesAutoresizingMaskIntoConstraints to NO on table views, their cells, or table header and footer views (or your controller's self.view, for that matter). It is okay to use constraints on the views within those views (cell content view or header and footer views). I added a simplified version of your code to viewDidLoad and it worked as expected. Note that you need to provide the footer with height and x position (y position and width are ignored),
UIView *tempFooter = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 50)];
UILabel *atext = [[UILabel alloc] init];
atext.translatesAutoresizingMaskIntoConstraints = NO;
atext.numberOfLines = 0;
[atext setText:@"Add Some Text"];
atext.textAlignment = NSTextAlignmentCenter;
atext.font = [UIFont italicSystemFontOfSize:14];
atext.textColor = [UIColor grayColor];
atext.backgroundColor = [UIColor clearColor];
atext.lineBreakMode = NSLineBreakByWordWrapping;
[tempFooter addSubview:atext];
NSDictionary *dict = NSDictionaryOfVariableBindings(atext);
[tempFooter addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-10-[atext]-10-|" options:0 metrics:nil views:dict]];
[tempFooter addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[atext]|" options:0 metrics:nil views:dict]];
self.tableView.tableFooterView = tempFooter;
I'm not sure what you were trying to accomplish with your tvatt3 constraint. The multiplier (you have 5) doesn't do anything with the top or left constraint, since the value of those attributes is 0. I used visual constraints, not the method you used, but when I used your code to add constraints, it worked as well.
source to share
I just came across an article that has a solution that works with Auto Layout: Dynamically Sizing Header or Footer Table Using Auto Layout from Collin Donnell
I tried this and it seems to work well.
source to share
hope this helps you
I'm not sure about this, but it helps me in my project, first add everything to contentView
(all subordinates and constraints)
[self.contentView addSubview:atext]
and then the code comes
NSLayoutConstraint *tvatt1 = [NSLayoutConstraint constraintWithItem:tempFooter
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:atext attribute:NSLayoutAttributeLeft
multiplier:1.0
constant:10.0];
code for left attribute
temfooter(must be equal) = 1.0*atext +10.0
those. temfooter must be equal to the modified atext, so you need to make sure your constraints are not wrong.
source to share
I was able to dynamically increase the width and height of the layout table of the layout by implementing @ rdelmar's solution for constraints and adding the following lines below. The same solution applies to the view of the table header.
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let tableFooter = tableView.tableFooterView {
let maxSize = CGSize(width: self.tableView.bounds.size.width,
height: CGFloat.greatestFiniteMagnitude)
let size = tableFooter.systemLayoutSizeFitting(maxSize)
let height = size.height
var headerFrame = tableFooter.frame
// If we don't have this check, viewDidLayoutSubviews() will get
// repeatedly, causing the app to hang.
if height != headerFrame.size.height {
headerFrame.size.height = height
tableFooter.frame = headerFrame
tableView.tableFooterView = tableFooter
}
}
}
source to share