Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITableViewCell with AutoLayout - contentView width constraint failure

I'm having problems with a dynamically-sized tableViewCell in iOS 8. While it visually looks fine, I get log output with AutoLayout errors. I've reduced it down to this simple example.

I'm adding a UILabel to my cell:

self.titleLabel = [[UILabel alloc] init];
self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
self.titleLabel.numberOfLines = 0;
self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
[self.contentView addSubview:self.titleLabel];

I'm creating my auto layout constraints in code, using Masonry, in updateConstraints:

[self.titleLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
[self.titleLabel updateConstraints:^(MASConstraintMaker *make) {
    make.leading.equalTo(self.contentView.leading).with.offset(padding.left);
    make.trailing.equalTo(self.contentView.trailing).with.offset(-padding.right);
    make.top.equalTo(self.contentView.top).with.offset(padding.top);
    make.bottom.equalTo(self.contentView.bottom).with.offset(-padding.bottom / 2);
}];

(I could do this in one step with make.edges, but the problem is the same)

This initially looks and works fine. Then, when I perform any modifications to the tableview and call [tableView endUpdates] (presumably triggering updateContraints), I get the following in the console log:

Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<MASLayoutConstraint:0x7ff4842551e0 UILabel:self.titleLabel.leading == UITableViewCellContentView:self.contentView.leading + 12>",
    "<MASLayoutConstraint:0x7ff484255240 UILabel:self.titleLabel.trailing == UITableViewCellContentView:self.contentView.trailing - 12>",
    "<NSLayoutConstraint:0x7ff484256df0 UITableViewCellContentView:self.contentView.width ==>"
)

Will attempt to recover by breaking constraint 
<MASLayoutConstraint:0x7ff484255240 UILabel:self.titleLabel.trailing == UITableViewCellContentView:self.contentView.trailing - 12>

I don't understand what the problem is here - I want the label to have padding, but why does that conflict with the overall width of the contentView?

Edit 1:

If I remove the padding, I no longer get the error. Is there some other way I can set it?

like image 248
blork Avatar asked Aug 23 '14 14:08

blork


3 Answers

You has three constraints with the same priority, which makes the system confuses how to satisfy them altogether. "", "", ""

As the width of your cell is also fixed according to your device width, I suggest using a little bit weak priority for your subview's constraints.

[self.titleLabel updateConstraints:^(MASConstraintMaker *make) {
    make.leading.equalTo(self.contentView.leading).with.offset(padding.left).priority(999);
    make.trailing.equalTo(self.contentView.trailing).with.offset(-padding.right).priority(999);
    make.top.equalTo(self.contentView.top).with.offset(padding.top);
    make.bottom.equalTo(self.contentView.bottom).with.offset(-padding.bottom / 2);
}];
like image 118
khanhlvg Avatar answered Nov 12 '22 17:11

khanhlvg


Did you configured UITableView before using dynamic cell height calculations? I have very similar issue and this code help me

- (void)viewDidLoad {
  [super viewDidLoad];
  self.tableView.estimatedRowHeight = 150;
  self.tableView.rowHeight = UITableViewAutomaticDimension;
}

I don't have experience with Masonry framework, but standard constraints works fine for me. Maybe you have something wrong with Masonry format?

    self.titleLabel = [[UILabel alloc] init];
    self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
    self.titleLabel.numberOfLines = 0;
    self.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
    [self.contentView addSubview:self.titleLabel];
    NSArray *constraintsHorizontal = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-12-[_titleLabel]-12-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_titleLabel)];
    NSArray *constraintsVertical = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-12-[_titleLabel]-12-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_titleLabel)];
    [self.contentView addConstraints:constraintsHorizontal];
    [self.contentView addConstraints:constraintsVertical];

Check test project at the https://dl.dropboxusercontent.com/u/48223929/TestTableCellsAutolayout.zip

like image 36
Vitalii Gozhenko Avatar answered Nov 12 '22 17:11

Vitalii Gozhenko


As per your question i've it seems that you've put the label in custom cell in xib or storyboard and now when you try to set the constraints manually it is not matching the constraints you've set programmatically. So what i suggest is create label programmatically and apply constraints.

you can also visit: Creating layout constraints programmatically

EDIT 1:
Try going through this link it might be helpful to you and it might solve the issue you are facing.
http://captechconsulting.com/blog/tyler-tillage/ios-8-tutorial-series-auto-sizing-table-cells

like image 1
Dhaivat Vyas Avatar answered Nov 12 '22 16:11

Dhaivat Vyas