What is NSLayoutConstraint “UIView-Encapsulated-Layout-Height” and how should I go about forcing it to recalculate cleanly?

牧云@^-^@ 提交于 2019-11-26 05:53:29

Try to lower the priority of your _collapsedtextHeightConstraint to 999. That way the system supplied UIView-Encapsulated-Layout-Height constraint always takes precedence.

It is based on what you return in -tableView:heightForRowAtIndexPath:. Make sure to return the right value and your own constraint and the generated one should be the same. The lower priority for your own constraint is only needed temporarily to prevent conflicts while collapse/expand animations are in flight.

Donald

I have a similar scenario: a table view with one row cell, in which there are a few lines of UILabel objects. I'm using iOS 8 and autolayout.

When I rotated I got the wrong system calculated row height (43.5 is much less than the actual height). It looks like:

"<NSLayoutConstraint:0x7bc2b2c0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7bc37f30(43.5)]>"

It's not just a warning. The layout of my table view cell is terrible - all text overlapped on one text line.

It surprises me that the following line "fixes" my problem magically(autolayout complains nothing and I get what I expect on screen):

myTableView.estimatedRowHeight = 2.0; // any number but 2.0 is the smallest one that works

with or without this line:

myTableView.rowHeight = UITableViewAutomaticDimension; // by itself this line only doesn't help fix my specific problem

I was able to get the warning to go away by specifying a priority on one of the values in the constraint the warning messages says it had to break (below "Will attempt to recover by breaking constraint"). It appears that as long as I set the priority to something greater than 49, the warning goes away.

For me this meant changing my constraint the warning said it attempted to break:

@"V:|[contentLabel]-[quoteeLabel]|"

to:

@"V:|-0@500-[contentLabel]-[quoteeLabel]|"

In fact, I can add a priority to any of the elements of that constraint and it will work. It doesn't seem to matter which one. My cells end up the proper height and the warning is not displayed. Roger, for your example, try adding @500 right after the 388 height value constraint (e.g. 388@500).

I'm not entirely sure why this works but I've done a little investigating. In the NSLayoutPriority enum, it appears that the NSLayoutPriorityFittingSizeCompression priority level is 50. The documentation for that priority level says:

When you send a fittingSize message to a view, the smallest size that is large enough for the view's contents is computed. This is the priority level with which the view wants to be as small as possible in that computation. It's quite low. It is generally not appropriate to make a constraint at exactly this priority. You want to be higher or lower.

The documentation for the referenced fittingSize message reads:

The minimum size of the view that satisfies the constraints it holds. (read-only)

AppKit sets this property to the best size available for the view, considering all of the constraints it and its subviews hold and satisfying a preference to make the view as small as possible. The size values in this property are never negative.

I haven't dug beyond that but it does seem to make sense that this has something to do with where the problem lies.

Clifton Labrum

I was able to resolve this error by removing a spurious cell.layoutIfNeeded() that I had in my tableView's cellForRowAt method.

Instead of informing the table view to update its constraints, try reloading the cell:

[tableView beginUpdates];

[_briefCell collapse:!_showFullBriefText];

[tableView reloadRowsAtIndexPaths:@[[tableView indexPathForCell:_briefCell]] withRowAnimation:UITableViewRowAnimationNone];

[tableView endUpdates];

UIView-Encapsulated-Layout-Height is probably the height the table view calculated for the cell during the initial load, based on the cell's constraints at that time.

Another possibility:

If you using auto layout to calculate the cell height (contentView's height, most of the time as below), and if you have uitableview separator, you need to add the separator height, in order to return for the cell height. Once you get the correct height, you won't have that autolayout warning.

- (CGFloat)calculateHeightForConfiguredSizingCell:(UITableViewCell *)sizingCell {
   [sizingCell setNeedsLayout];
   [sizingCell layoutIfNeeded];
   CGSize size = [sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
   return size.height; // should + 1 here if my uitableviewseparatorstyle is not none

}

As mentioned by Jesse in question's comment, this works for me:

self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight;

FYI, this issue not occurs in iOS 10.

I had this error when using UITableViewAutomaticDimension and changing a height constraint on a view inside the cell.

I finally figured out that it was due to the constraint constant value not being rounded up to the nearest integer.

let neededHeight = width / ratio // This is a CGFloat like 133.2353
constraintPictureHeight.constant = neededHeight // Causes constraint error
constraintPictureHeight.constant = ceil(neededHeight) // All good!

Sizing the text view to fit its content, and updating the height constraint constant to the resulting height, fixed the UIView-Encapsulated-Layout-Height constraint conflict for me, e.g.:

[self.textView sizeToFit];
self.textViewHeightConstraint.constant = self.textView.frame.size.height;

After spending some hours scratching my head with this bug I finally found a solution that worked for me. my main problem was that I had multiple nibs registered for different cell types but one cell type specifically was allowed to have different sizes(not all instances of that cell are going to be the same size). so the issue arose when the tableview was trying to dequeue a cell of that type and it happened to have a different height. I solved it by setting

self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight; self.frame = CGRectMake(0, 0, self.frame.size.width, {correct height});

whenever the cell had its data to calculate its size. I figure it can be in

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

something like

cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight; cell.frame = CGRectMake(0, 0, self.frame.size.width, {correct height});

Hope this helps!

TableView get height for cell at indexPath from delegate. then get cell from cellForRowAtIndexPath:

top (10@1000)
    cell
bottom (0@1000)

if cell.contentView.height:0 //<-> (UIView-Encapsulated-Layout-Height:0@1000) top(10@1000) conflicted with (UIView-Encapsulated-Layout-Height:0@1000),

because of they priorities are is equal 1000. We need set top priority under UIView-Encapsulated-Layout-Height's priority.

I was getting a message like this:

Unable to simultaneously satisfy constraints...
...
...
...
NSLayoutConstraint:0x7fe74bdf7e50 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fe75330c5c0(21.5)]
...
...
Will attempt to recover by breaking constraint NSLayoutConstraint:0x7fe0f9b200c0 UITableViewCellContentView:0x7fe0f9b1e090.bottomMargin == UILabel:0x7fe0f9b1e970.bottom

I'm using a custom UITableViewCell with UITableViewAutomaticDimension for the height. And I've also implemented the estimatedHeightForRowAtIndex: method.

The constraint that was giving me problems looked something like this

[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[title]-|" options:0 metrics:nil views:views];

Changing the constraint to this will fix the problem, but like another answer I felt that this wasn't correct, as it lowers the priority of a constraint that I want to be required:

[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-6@999-[title]-6@999-|" options:0 metrics:nil views:views];

However, what I noticed is that if I actually just remove the priority, this also works and I don't get the breaking constraint logs:

[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-6-[title]-6-|" options:0 metrics:nil views:views];

This is a bit of a mystery as to what the difference is between |-6-[title]-6-| and |-[title-|. But specifying the size isn't an issue for me and it gets rid of the logs, and I don't need to lower the priority of my required constraints.

Set this view.translatesAutoresizingMaskIntoConstraints = NO; should resolve this issue.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!