13

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?

Community
  • 1
  • 1
blork
  • 2,150
  • 6
  • 26
  • 45
  • Have you tried using visual format instead? `NSArray *formats = @[ @"H:|-12-[tl]-12-|", @"V:|-6-[tl]-6-|" ];` And then possibly applying those to the content view? – Mike Welsh Dec 03 '14 at 22:11
  • Thanks for checking out my question! Unfortunately, using the visual format language results in exactly the same error as above. :/ – blork Dec 04 '14 at 20:01
  • Have you tried making the trailing padding >= instead of == ? – Mike Taverne Dec 06 '14 at 19:44
  • Making the constraint `greaterThanOrEqualTo` doesn't work - the right edge of the label is then free to expand out as much as it wants, and so the label becomes single line and the cell very wide. Trying `lessThanOrEqualTo` results in the same error as `equals`. – blork Dec 06 '14 at 23:03
  • Does this help? http://derpturkey.com/autosize-uitableviewcell-height-programmatically/ – Mike Taverne Dec 09 '14 at 07:19
  • Try lowering the self.contentView.width compression resistance. The cell is trying to shrink or grow in width but the width of the cell.contentView is set to stay at a certain width. – Brooks Hanes Dec 09 '14 at 15:37
  • I've tried UILayoutPriorityDefaultLow (and required, and all the constants inbetween) for UILayoutConstraintAxisHorizontal - all give me the same problem. – blork Dec 09 '14 at 21:21
  • I've just had a very similar issue to this whilst using Masonry to layout labels in the `contentView`. I ended up setting the background colour on one of the labels and then magically it stopped complaining about the broken constraints. I removed the background colour and the error didn't return. However, the background colour did reveal it's ignoring my constraints, and the label view is only as wide as the text in the label, not as wide as the `contentView` as I set it. Can also see this same result if I center the labels. – Hodson Dec 12 '14 at 12:48
  • I have now [created an issue over at the Masonry repo about this](https://github.com/Masonry/Masonry/issues/134) – Hodson Dec 12 '14 at 13:00
  • Oddly enough this is happening for me too. I am working on a project with iOS 7 as the deployment target and I get constraint related errors coming from by subclassed UITableViewCell. I changed the CGFloat being returned in the tableview heightForRowAtIndexPath to make sure that its total equalled or exceeded that of the defined heights of the content in the table view cell. I am new to iOS Autolayout so I am looking for good resources on how to get this exact. – matfin Jan 07 '15 at 16:10

3 Answers3

3

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);
}];
khanhlvg
  • 781
  • 7
  • 9
  • Can't believe I hadn't tried it before, but starting again with this works great for me. At last, thanks! – blork Dec 30 '14 at 20:07
1

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

Community
  • 1
  • 1
Dhaivat Vyas
  • 2,926
  • 1
  • 16
  • 26
  • Late reply - the cell was not from a nib or storyboard, but entirely in code. I switched to using a nib, and I'm still encountering this same error. – blork Dec 03 '14 at 20:16
  • Hi, sorry for late reply. Please visit the link it might be helpful though the constraints are set in storyboard but it can be set in similar through coding. http://www.appcoda.com/self-sizing-cells/ – Dhaivat Vyas Dec 10 '14 at 03:06
1

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

Vitalii Gozhenko
  • 9,220
  • 2
  • 48
  • 66
  • Yes, I'm pretty sure I have it configured correctly already. I have this exact code (though my height is 100) in my viewDidLoad. – blork Dec 09 '14 at 21:23
  • I've tried to implement it via standard constraints constructor, and it works for me. I think there can be a problem with Masorny framework – Vitalii Gozhenko Dec 09 '14 at 23:38