306

I have a UITableView running under iOS 8 and I'm using automatic cell heights from constraints in a storyboard.

One of my cells contains a single UITextView and I need it to contract and expand based on user input - tap to shrink/expand the text.

I'm doing this by adding a runtime constraint to the text view and changing the constant on the constraint in response to user events:

-(void)collapse:(BOOL)collapse; {

    _collapsed = collapse;

    if(collapse)
        [_collapsedtextHeightConstraint setConstant: kCollapsedHeight]; // 70.0
    else
        [_collapsedtextHeightConstraint setConstant: [self idealCellHeightToShowFullText]];

    [self setNeedsUpdateConstraints];

}

Whenver I do this, I wrap it in tableView updates and call [tableView setNeedsUpdateConstraints]:

[tableView beginUpdates];

[_briefCell collapse:!_showFullBriefText];

[tableView setNeedsUpdateConstraints];
// I have also tried 
// [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
// with exactly the same results.

[tableView endUpdates];

When I do this, my cell does expand (and animates whilst doing it) but I get a constraints warning:

2014-07-31 13:29:51.792 OneFlatEarth[5505:730175] 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) 

(

    "<NSLayoutConstraint:0x7f94dced2b60 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'(388)]>",

    "<NSLayoutConstraint:0x7f94dced2260 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...']-(15)-|   (Names: '|':UITableViewCellContentView:0x7f94de5773a0 )>",

    "<NSLayoutConstraint:0x7f94dced2350 V:|-(6)-[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...']   (Names: '|':UITableViewCellContentView:0x7f94de5773a0 )>",

    "<NSLayoutConstraint:0x7f94dced6480 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7f94de5773a0(91)]>"
 )

Will attempt to recover by breaking constraint 

<NSLayoutConstraint:0x7f94dced2b60 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'(388)]>

388 is my calculated height, the other constraints on the UITextView are mine from Xcode/IB.

The final one is bothering me - I'm guessing that UIView-Encapsulated-Layout-Height is the calculated height of the cell when it is first rendered - (I set my UITextView height to be >= 70.0) however it doesn't seem right that this derived constraint then overrules an updated user cnstraint.

Worse, although the layout code says it's trying to break my height constraint, it doesn't - it goes on to recalculate the cell height and everything draws as I would like.

So, what is NSLayoutConstraint UIView-Encapsulated-Layout-Height (I'm guessing it is the calculated height for automatic cell sizing) and how should I go about forcing it to recalculate cleanly?

Rog
  • 17,070
  • 9
  • 50
  • 73
  • 3
    cross posted to Apple dev forums: https://devforums.apple.com/thread/238803 – Rog Jul 31 '14 at 12:57
  • I heard a rumour that auto layout is still changing. Maybe this is a bug. – Rog Aug 04 '14 at 08:49
  • For all those people uprooting, thanks. I would also suggest going to the Apple bug and "me too"ing it to try and bring it to the attention of an Apple dev. – Rog Aug 18 '14 at 13:09
  • My defect report to Apple has been marked as a duplicate which I _think_ means it is a defect. – Rog Aug 27 '14 at 07:29
  • Ortwin's suggestion of lowering the priority works in that it stops the warning but it doesn't have the correct effect on the cell. I think this is an Apple bug and encourage others to create a rdar for it. – Rog Oct 13 '14 at 08:54
  • 3
    I resolved a similar issue in the following way and it works on iOS 7/8. 1) Lower one of the constraint priorities to 750. I would try the 1st or the 2nd 2) In the cell subclass in awakeFromNib set `self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight;`. I think that initially setting the autoresize mask stops the last constraint from being added. I found this solution here: https://github.com/wordpress-mobile/WordPress-iOS/commit/0ce857fd19202f26aea2aa5c64eb48f913aa457c – Jesse Nov 14 '14 at 00:22
  • Lowering the priority of one of my constraints simply lets the Apple constraint win which is not what I want - see @Ortwin's answer below. When you set the autoresizingMask set, do you also have translatesAutoresizingMaskIntoConstraints set? Either way, this sounds like mixing two systems - or an Apple bug in Autolayout. – Rog Nov 14 '14 at 09:37
  • 3
    @RogerNolan, any news? I found the same issue while playing with Auto-layout in Interface Builder. Some cells causes this issue, some not. – orkenstein Nov 25 '14 at 12:07
  • Came across this problem myself today. I found that in addition to setting: `self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight;` I also need to add `self.frame = CGRectMake(0, 0, self.frame.size.width, 50);` after it and then the problem went away. I posted an answer to a similar question here: http://stackoverflow.com/questions/25087969/auto-sizing-uitableviewcell-in-ios-8/29138115#29138115 – Zhang Mar 19 '15 at 06:03
  • 4
    I don't think that adding an autoresizing mark is a good solution. – Rog Mar 20 '15 at 09:16
  • 1
    @RogerNolan are you generating this cell in IB prior to performing these layout changes? I've been debugging the same problem but I wasn't adding any extra constraints. I managed to suppress the warning by rebuilding my view from scratch, and when I diff'ed the 2 storyboard files the only difference was that the version with the warnings was missing the line `` in its definition, leading me to believe this is an IB bug. At least mine was anyway. – Ell Neal Mar 31 '15 at 15:56
  • I only. get this warning when I set my tableview to editing, so it seems this warning is wrong, like so many many other auto layout warnings. – RunLoop Jul 26 '20 at 05:15

23 Answers23

328

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.

Addition: While it may be debatable if the system supplied constraint is correct or not, there's no point in fighting the framework. Simply accept that the system constraint takes precedence. If you think the system constraint is wrong, make sure to return the correct rowHeight from the delegate.

Ortwin Gentz
  • 52,648
  • 24
  • 135
  • 213
  • 94
    That would achieve exactly the opposite of what I want. The UIView-Encapsulated-Layout-Height is wrong - it belongs to the previous layout. – Rog Sep 16 '14 at 13:21
  • 9
    The `UIView-Encapsulated-Layout-Height` constraint is added by UITableView once the heights are determined. I calculate the height based on the `systemLayoutSizeFittingSize` of the contentView. Here, the `UIView-Encapsulated-Layout-Height` doesn't matter. Then, the tableView sets the contentSize explicitly to the value returned by `heightForRowAtIndexPath:`. In this case it's correct to lower our custom constraints' priority because the tableView constraint must take precedence after the rowHeights are calculated. – Ortwin Gentz Sep 16 '14 at 14:03
  • 1
    @ortwin heightForRowAtIndexPath is olde worlde isn't it? You should not implement it when you have autolayout and self sizing cells. – Rog Sep 22 '14 at 10:48
  • 1
    @RogerNolan we had to support iOS 7 as well. – Ortwin Gentz Sep 22 '14 at 17:24
  • 13
    @OrtwinGentz: Still don't get the point *it's correct to lower our custom constraints' priority because the tableView constraint must take precedence after the rowHeights are calculated*. The thing is that `UIView-Encapsulated-Layout-Height` is wrong if I don't lower the priority... – testing Nov 12 '14 at 08:48
  • 1
    This doesn't work for me... it just lets iOS break the constraint, so that my cells are shorter than I need them to be. How can I get iOS to recalculate the cell height instead? – ndbroadbent Feb 10 '15 at 12:51
  • 1
    @nathan.f77 When you change the cell size you have to tell the tableView: `[tableView beginUpdates]; [tableView endUpdates];` Then the tableView will ask the delegate via `-heightForRowAtIndexPath:` for the new heights. – Ortwin Gentz Feb 10 '15 at 15:04
  • 4
    I'm not really changing the cell heights, I'm trying to reuse an existing cell from `dequeueReusableCellWithIdentifier`. So the cell height is changing inside my tableView's `cellForRowAtIndexPath` function. I would just like to get rid of this `UIView-Encapsulated-Layout-Height` constraint because it doesn't seem to be needed, since the rest of my contraints will lead to the same height. It's just preventing me from updating a reuseable cell's height. – ndbroadbent Feb 17 '15 at 13:38
  • 2
    Don't fight the framework. `UIView-Encapsulated-Layout-Height` is automatically added by `UITableView`. Since this constraint always has a priority of 1000 your vertical constraints should have a lower priority to avoid a conflict. – Ortwin Gentz Feb 17 '15 at 17:01
  • 42
    I maintain that's avoiding conflict not fixing the actual problem - although as this still feels like an Apple bug, I think it's probably the right thing to do. Especially in light of the fact that Apple recalculate this constraint and everything does lay out correctly after the error prints. – Rog Mar 18 '15 at 12:15
  • 14
    -1 for this answer since it assumes the constraint being added is correct. The added `UIView-Encapsulated-Layout-Width` in my case is just wrong, but it seems to be preferred over my explicit constraints at runtime. – ray Jun 01 '15 at 22:00
  • 3
    @ray See my updated answer. Don't fight the framework and simply accept that the system constraint takes precedence. If you think the system constraint is wrong, make sure to return the correct rowHeight from the delegate. – Ortwin Gentz Jun 03 '15 at 19:08
  • I think what is happening is the system uses autoresizing mask constraints for a cell content view. So if you specifically set self.translatesAutoresizingMaskIntoConstraints = NO, you interfere with the layout system. Then make sure any constraint changes are done within begin and end updates, and that at least one constraint is 999 as recommended for each axis. – TigerCoding Aug 27 '15 at 22:12
  • 1
    Hi @OrtwinGentz, thanks for the AAA tip. I had a situation where, I was using native select on rows, and then in the cell using setSelected (NOT as is more usual in the view controller) I was expanding or contracting a UILabel by a few lines. **In that case** the situation is **exactly as you describe**, as far as I can see. Can't thank you enough. RogerNolan I suspect that the subtle difference you bring to the fore (and I want it explained, too), depends on the situation. Note all readers you must use [THIS INCREDIBLE TIP](http://stackoverflow.com/a/31833436/294884) to resolve these issues. – Fattie Sep 23 '15 at 13:59
  • 2
    @RogerNolan this answer is not a fix for the problem but rather a dirty workaround. You should not adjust the priorities of your constraints just because there is something else created. Apple docs say that only prio 1000 is required, when you put a lower number then you eventually ask a different layout from the system. And the advice "don't fight the framework" is at least strange. The solution is simple - you just need to provide "estimatedHeightForRowAtIndexPath". In my case making it bigger than the actual height worked. More precisely, return maximum height for your cell's current state. – frangulyan Feb 11 '16 at 00:19
  • 1
    I can confirm that making my constraint's priority be `UILayoutPriorityRequired-1` (999) and calling `tableView.beginUpdates(); tableView.endUpdates()` does the trick. – NiñoScript Feb 24 '16 at 19:35
  • 1
    Here it is a year later, and Apple has not clarified or corrected this cluster-code. Every developer who tries to make a custom keyboard runs into this seemingly simple issue. – Tjalsma May 29 '16 at 19:25
73

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
Rajan Balana
  • 3,775
  • 25
  • 42
Golden Thumb
  • 2,531
  • 21
  • 20
  • 10
    Finally! This is a correct answer. In WWDC session, it was mentioned, if you gonna use the automatic row height sizing, then you shall set an estimatedRowHeight or bad things happens. (Yes, Apple really nasty things happened) – Abdalrahman Shatou Jan 26 '15 at 13:57
  • Indeed, simply setting the estimatedRowHeight property solved all my problems and thus seems mandatory. It's worth noting that rather than just setting the property to 2.0, it's better to actually estimate the row height for scrolling performance reasons. – Rachid Finge Jr Apr 13 '15 at 23:31
  • with Obj-C the only way that fixed the problem was overriding the method from the tableview delegate, thank you a lot! -(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{ return 2.0; } – JRafaelM Apr 17 '15 at 11:33
  • 61
    FWIW, adding the estimate has made no difference at all for me. – Benjohn May 12 '15 at 18:15
  • 4
    Heh. I'm back at this same answer again, and went to implement it with joy and hope. Once again, it's made no difference for me :-) – Benjohn Jul 20 '15 at 12:26
  • yes, that's the only correct answer for UITableViewAutomaticDimension – Paul T. Sep 01 '15 at 04:28
  • 4
    Estimates returned by tableView:estimatedHeightForRowAtIndexPath: *MUST* be at least as large as the cell. Otherwise, the calculated height of the table will be less than the actual height, and the table may scroll up (e.g. after unwind segue returns to the table). UITableViewAutomaticDimension should not be used. – Matt Nov 05 '15 at 21:55
  • Not sure what performance impact this has (none visually), but I found that I still got issues if the intrinsic size of the subviews + constraints was larger than the estimated height. Setting the `self.tableView.estimatedRowHeight = 1000` (some arbitrary large number) eliminated the incompatible constraint. – Stan Jun 09 '16 at 18:19
  • If the gap between estimatedRowHeight and the real height is too large, the tableView may flicker during fast scrolling. – Jinghan Wang Sep 05 '16 at 19:20
  • Can' add `estimatedRowHeight`,this make my scroll buggy and makes tableView jump and flicker after any reloadCell or reloadSections. – Caio Dec 16 '16 at 16:41
  • if estimatedRowHeight doesn't work, then try `tableView.translatesAutoresizingMaskIntoConstraints = false`. I was having this constraint issue with a tableview in a container view of a primary view controller that already had the estimatedRowHeight set, and it was not until I made sure it wasn't making constraints from the autoresizing mask that I stopped getting a bunch of constraint errors. – Natalia Dec 21 '16 at 04:41
  • 1
    Note that the lower the `estimatedRowHeight` the more often `cellForRowAtIndexPath` will be called initially. tableview height divided by estimatedRowHeight times, to be exact. On an 12 inch iPad Pro, this can potentially be a number in the thousands and will hammer the datasource and can result in a significant delay. – Mojo66 Dec 30 '16 at 11:43
  • Setting `estimatedRowHeight` on the table view and then returning `automaticDimension` from the row height delegate method worked for me. Previously I was not setting the `estimatedRowHeight` and autolayout was spitting a conflicting constraint message. If you are attempting to set `automaticDimension` for the height, and adding `estimatedRowHeight` does not work for you, make sure that the cell you're trying to render has a clear intrinsic content size or else your cell probably will not render correctly. – FateNuller Feb 14 '20 at 21:56
  • I had a similar problem. It worked for me after following these steps: 1) setup `tableView.rowHeight` to `UITableView.automaticDimension`, 2) setup `tableView.estimatedRowHeight` to a sane value, e.g. 44, and 3) update constraints only within `updateConstraints` before the call to `super`. I previously updated my constraints in `layoutSubviews` which seemed to be the cause for the warning in my case. – mschmidt Apr 17 '20 at 19:04
55

99.9% of the time, while using custom cells or headers, all conflicts of UITableViews occur when the table loads of the first time. Once loaded you will usually not see the conflict again.

This happens because most developers typically use a fixed height or anchor constraint of some sort to layout an element in the cell/header. The conflict occurs because when the UITableView first loads/being laid out, it sets the height of its cells to 0. This obviously conflicts with your own constraints. To solve this, simply set any fixed height constraints to a lower priority (.defaultHigh). Read carefully the console message and see which constraint the layout system decided to break. Usually this is the one that needs its priority changed. You can change the priority like this:

let companyNameTopConstraint = companyNameLabel.topAnchor.constraint(equalTo: companyImageView.bottomAnchor, constant: 15)
    companyNameTopConstraint.priority = .defaultHigh

NSLayoutConstraint.activate([
            companyNameTopConstraint,
           the rest of your constraints here
            ])
UMAD
  • 597
  • 4
  • 11
  • 4
    Beautiful explanation. – Glenn Posadas Apr 10 '20 at 12:38
  • Awesome explanation. – Sourabh Shekhar Dec 07 '20 at 11:30
  • That's right, thanks. Worked for me. But I can't undesrstand logic behind that and can't see that's the cell's height is 0 in the moment of this error. The logs in console shows something like this `'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7fa661635050.height == 150`. It's meaning that the cell's content view got it's height. And for me there is no views with height of 0. – surfrider Jul 05 '21 at 09:22
35

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.

Jeff Bowen
  • 5,904
  • 1
  • 28
  • 41
  • Thatks Jeff. Still feels like a bug to me. Apple have not responsed to the rdar though :-( – Rog Nov 24 '14 at 08:50
13

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

scopchanov
  • 7,966
  • 10
  • 40
  • 68
Clifton Labrum
  • 13,053
  • 9
  • 65
  • 128
9

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.

Austin
  • 5,625
  • 1
  • 29
  • 43
  • I should have stated in my question, I've tried this and it doesn't work. I agree on your guess about UIView-Encapsulated-Layout-Height – Rog Aug 13 '14 at 09:53
  • 6
    Have the bounty anyway for at least submitting an answer. Seems like SO will just let it evaporate otherwise. – Rog Aug 13 '14 at 09:56
6

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

}
Cullen SUN
  • 3,517
  • 3
  • 32
  • 33
  • That did help me in a case where I got layout height ambiguities in a pretty complex cell layout only in some simulators (iPad 6 Plus). It appears to me that due to some internal rounding errors the content is a bit squeezed and if the constraints are not prepared to be squeezed than I got ambiguities. So instead of returning `UITableViewAutomaticDimension` in `heightForRowAtIndexPath` I return `[sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize] + 0.1` – Leo Apr 28 '18 at 15:44
  • I mean of course `[sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + 0.1` – Leo Apr 28 '18 at 15:52
  • Staggeringly; removing the separator is what got my table behaving, so thanks. – royalmurder Nov 18 '19 at 18:17
6

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

self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight;

FYI, this issue not occurs in iOS 10.

Phu Nguyen
  • 261
  • 3
  • 6
6

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!
Che
  • 1,691
  • 1
  • 15
  • 8
  • 2
    This was the comment that clued me into my issue. I have an image cell that loads dynamically (grows and shrinks) and a tableview with estimatedRowHeight = 50 and rowHeight = UITableViewAutomaticDimension. I was still breaking on constraints even though the tableview was the correct height. Turns out the separators were 0.3333 in height and that was what was kicking my image size constraint in the cell to be broken. After turning off separators all was well. Thanks Che for giving me what to look for. – migs647 Dec 07 '18 at 18:04
  • 1
    In this case create an extra constraint, e.g., bottomMargin >= view.bottomMargin+1@900. AutoLayout tries to accommodate the extra 1 point, resizes the cell, gets confused because of the separator height, tries to break/relax some constraints, finds the one @900, and discards that. You get the layout you want without warnings. – Anton Dec 15 '18 at 20:29
  • save my day. few hours anyway – Anton Tropashko Mar 13 '19 at 14:37
4

I had a similar problem with a collection view cell.

I solved it by lowering the priority of the final constraint that was linked to the bottom of the cell (the last one in the chain from the top to the bottom of the view - this is ultimately what determines its height) to 999.

The height of the cell was correct, and the warnings went away.

Rich
  • 111
  • 7
4

I had the same issue.For me the error was of 0.5 pixel.

2020-08-06 21:33:20.947369+0530 DemoNestedTableView[4181:384993] [LayoutConstraints] 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. 
(

        "<NSLayoutConstraint:0x600000a3abc0 UICollectionView:0x7fde0780c200.height == 326   (active)>",
        "<NSLayoutConstraint:0x600000a3ae40 V:|-(0)-[UICollectionView:0x7fde0780c200]   (active, names: '|':UITableViewCellContentView:0x7fde05e0cb10 )>",
        "<NSLayoutConstraint:0x600000a3af30 V:[UICollectionView:0x7fde0780c200]-(0)-|   (active, names: '|':UITableViewCellContentView:0x7fde05e0cb10 )>",
        "<NSLayoutConstraint:0x600000a2a4e0 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7fde05e0cb10.height == 326.5   (active)>"
    )

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x600000a3abc0 UICollectionView:0x7fde0780c200.height == 326   (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.

So just added this and it worked.

self.tableView.separatorStyle = .none
mokagio
  • 16,391
  • 3
  • 51
  • 58
K_Mohit
  • 528
  • 3
  • 17
2

No one answered it how to solve the case in storyboard. You have the case of mine, top bottom constraint with fixed height with priority 1000. That is why, when first time loading , as the table view cell height is 0, tries to set the element with the fixed height, causing a constraint conflict. (I am trying to insert 40 pixel in a 0 pixel height area, so compiler tries discarding the 40 pixel height). Once the tableview loaded, it will not generate (Like pop back to the tableview or switching tab bar tab)

So change the priority from required @1000 to High @750 or Low @250. For the first time loading, lower priorities will not be considered, then resizing the all constraints in layoutSubviews()

enter image description here

Ankur Lahiry
  • 2,253
  • 1
  • 15
  • 25
1

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;
Kim
  • 1,412
  • 1
  • 11
  • 10
1

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!

1

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

kathy zhou
  • 62
  • 3
1

In my case, the issue was with a vertical UIStackView inside a UITableViewCell, which was showing/hiding rows based on the data. I am using auto-sizing cells and the cell itself was always displayed correctly, with the correct height. Just the logs were full of constraints exceptions about UIView-Encapsulated-Layout-Height.

I resolved the issue by setting a lower priority to the UIStackView's top and bottom constraints (999 instead of the default 1000). Now there are no constraints exceptions, and the table looks and behaves identically.

shelll
  • 3,234
  • 3
  • 33
  • 67
1

If you have UIView-Encapsulated-Layout-Height warning in debug console with Xib/Storyboard.

You should do these thing:

  1. Go Size Inspector page
  2. Check the Row Height checkbox Automatic. Record the Row Height Value
  3. Set tableView.estimatedRowHeight to that Value

NO MORE Warning⚠️

Frank
  • 320
  • 1
  • 8
  • If Apple won't fix this problem, it may be called a fix. (But I prefer to call it `workaround`) – Frank Jun 17 '21 at 02:28
0

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.

0

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.

user1687195
  • 9,058
  • 2
  • 15
  • 15
0

In my case, I did manage to get rid of the warning by setting the priority of the constraint that Xcode was complaining about to 750, but the cell was still using a wrong height after deleting and reinserting it into the table.

The problem came from the fact that the calls to the beginUpdates() and endUpdates() (in between where I did my deletions and insertions) methods were encapsulated in an UIView.animate(withDuration:) animation block, where I wanted to control the duration of the animation when updating the table. Removing the call to the animation block fixed the issue for me.

0

Che's answer set me on the right track. I had created an outlet of a height constraint in my UITableViewCell, and I was changing this height constraint at run-time based on some conditions.

Instead of this -

myHeightConstraint.constant = 0.0

I wrote -

myHeightConstraint.constant = CGFloat.zero

and that fixed this warning for me. Basically whatever height is returned in the heightForRowAt method should be the same as the height calculated using the constraints at runtime.

Dhruv Saraswat
  • 858
  • 9
  • 13
0

The simple fact is this is a long-standing undeniable bug from Apple.

It's totally illogical, but, you have to reduce the priority of your final bottom constraint in the vertical chain of constraints.

enter image description here

That's all there is to it, end of story. Apple haven't fixed this in 20? years so it's unlikely they ever will.

UIKit has a number of "totally insane" strange behaviors or plain bugs, that will never be fixed, and this is one of them.

Fattie
  • 27,874
  • 70
  • 431
  • 719
-1

If UIView-Encapsulated-Layout-Width and UIView-Encapsulated-Layout-Height is zero for you, you might use the wrong table view/collection view instance when returning a cell using dequeueReusableCell.

Tamás Sengel
  • 55,884
  • 29
  • 169
  • 223