Troubleshooting: iOS auto layout warning about UIView-Encapsulated-Layout-Height
In a table view cell layout, there is no layout constraints issue in xcode. However during run time, xcode console report following layout constraints issue:
[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:0x6000012c0190 UIView:0x7fdefe74a240.height == 1 (active)>", "<NSLayoutConstraint:0x6000012c0960 MyModule.MyAwesomeControl:0x7fdefe721d90.height == 48 (active)>", "<NSLayoutConstraint:0x6000012c40a0 V:|-(16)-[UIImageView:0x7fdefe747ae0] (active, names: '|':UITableViewCellContentView:0x7fdefe747940 )>", "<NSLayoutConstraint:0x6000012c4410 V:[UIImageView:0x7fdefe747ae0]-(12)-[UIView:0x7fdefe74a240] (active)>", "<NSLayoutConstraint:0x6000012c4690 V:[UIView:0x7fdefe74a240]-(20)-[UITextView:0x7fdefe8f3400'No network is currently d...'] (active)>", "<NSLayoutConstraint:0x6000012c47d0 V:[MyModule.MyAwesomeControl:0x7fdefe721d90]-(50)-| (active, names: '|':UITableViewCellContentView:0x7fdefe747940 )>", "<NSLayoutConstraint:0x6000012c4820 MyModule.MyAwesomeControl:0x7fdefe721d90.top == UITextView:0x7fdefe8f3400'Awesome text here...'.top + 56 (active)>", "<NSLayoutConstraint:0x6000012b9040 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7fdefe747940.height == 32 (active)>" ) Will attempt to recover by breaking constraint <NSLayoutConstraint:0x6000012c0960 MyModule.MyAwesomeControl:0x7fdefe721d90.height == 48 (active)>
The layout constraints include
UIView-Encapsulated-Layout-Height which not part of original view layout constraints.
However from the UI perspective, thought this warning exist, the layout looks correctly, it didn’t break the constraint mentioned above. It actually break
'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7fdefe747940.height == 32. It is kind of weird.
UIView-Encapsulated-Layout-Height constraint is added by
UITableView, the value
32 (or whatever number) should be cell height.
However in this case the actual cell height is not
32 is estimated row height.
Auto Height for TableView Cell
In iOS, you can use Auto Layout to define the height of a table view cell; however, the feature is not enabled by default.
Normally, a cell’s height is determined by the table view delegate’s
To enable self-sizing table view cells, you must set the table view’s
rowHeight property to
You must also assign a value to the
As soon as both of these properties are set, the system uses Auto Layout to calculate the row’s actual height.
First make sure let
UITableView determine its cell height automatically with use following code:
tableView.estimatedRowHeight = 32; // or any number, but need set a number to make it work. tableView.rowHeight = UITableView.automaticDimension
After this settings, the cell should calculate its height automatically.
Then lay out the table view cell’s content within the cell’s content view. To define the cell’s height, you need an unbroken chain of constraints and views (with defined heights) to fill the area between the content view’s top edge and its bottom edge. If your views have intrinsic content heights, the system uses those values. If not, you must add the appropriate height constraints, either to the views or to the content view itself.
Additionally, try to make the estimated row height as accurate as possible. The system calculates items such as the scroll bar heights based on these estimates. The more accurate the estimates, the more seamless the user experience becomes.
The Real Scenario
From the UI perspective, thought this warning exist, the layout looks correctly, it didn’t break the constraint mentioned above. It actually break
'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7fdefe747940.height == 32. Looks like Xcode give wrong warning at the first place.
After code review I found a call to
layoutIfNeeded() after change some view attributes.
I suspect maybe this caused issue, the reason is when call
layoutIfNeeded() it lays out the subviews immediately. Since the cell height is not determined yet, so it use estimated height and caused warning.
After actual cell height is determined the cell will layout one more time with correct cell height. This explain why UI looks correct and not use estimated row height.
Use this method to force the view to update its layout immediately. When using Auto Layout, the layout engine updates the position of views as needed to satisfy changes in constraints. Using the view that receives the message as the root view, this method lays out the view subtree starting at the root. If no layout updates are pending, this method exits without modifying the layout or calling any layout-related callbacks.
First make sure table view cell is set to auto height:
tableView.rowHeight = UITableView.automaticDimension tableView.estimatedRowHeight = 32;
Then the solution to remove this weird
UIView-Encapsulated-Layout-Height warning is simple:
find and remove un-necessary
Then Xcode will not report any layout constraints warnings and layout is correct.
Encrypted your DNS to protect your privacy and firewall to block phishing, malicious domains, block ads in all browsers and apps