In my app I have an UITableView with a header created with .xib, this is the class:
class ViewHomeHeader: UIView {
class func instanceFromNib() -> ViewHomeHeader {
return UINib(nibName: "ViewHomeHeader", bundle: nil).instantiate(withOwner: self, options: nil).first as! ViewHomeHeader
}
}
I'm adding it to tableHeaderView:
let viewHomeHeader = ViewHomeHeader.instanceFromNib()
tableView.tableHeaderView = viewHomeHeader
This is the .xib with just one label and its relative constraints.
That's the result if I run on simulator (same on device)
I can't understand why the height is bigger than 21.
With the "Debug View Hierarchy" I can see that is not using the label height but the UIView-Encapsulated-Layout-Height
Console log:
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:0x28079f9d0 UILabel:0x104529b80'Label'.height == 21 (active)>",
"<NSLayoutConstraint:0x2807ac0a0 UILayoutGuide:0x281d9d500'UIViewSafeAreaLayoutGuide'.bottom == UILabel:0x104529b80'Label'.bottom + 17 (active)>",
"<NSLayoutConstraint:0x2807ac140 UILabel:0x104529b80'Label'.top == UILayoutGuide:0x281d9d500'UIViewSafeAreaLayoutGuide'.top + 18 (active)>",
"<NSLayoutConstraint:0x2807ae490 'UIView-Encapsulated-Layout-Height' Jordy.ViewHomeHeader:0x104529790.height == 143 (active)>",
"<NSLayoutConstraint:0x2807ac000 'UIViewSafeAreaLayoutGuide-bottom' V:[UILayoutGuide:0x281d9d500'UIViewSafeAreaLayoutGuide']-(0)-| (active, names: '|':Jordy.ViewHomeHeader:0x104529790 )>",
"<NSLayoutConstraint:0x28079fc50 'UIViewSafeAreaLayoutGuide-top' V:|-(0)-[UILayoutGuide:0x281d9d500'UIViewSafeAreaLayoutGuide'] (active, names: '|':Jordy.ViewHomeHeader:0x104529790 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x28079f9d0 UILabel:0x104529b80'Label'.height == 21 (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.
As specified in the documentation:
When assigning a view to this property, set the height of that view to
a nonzero value. The table view respects only the height of your
view's frame rectangle; it adjusts the width of your header view
automatically to match the table view's width.
So you have to set the header size before setting it.
If your header has a height which depends on its content, here is a possible solution:
let header = HeaderView()
let widthConstraint = header.widthAnchor.constraint(equalToConstant: view.bounds.width)
header.translatesAutoresizingMaskIntoConstraints = false
widthConstraint.isActive = true
let targetSize = header.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
header.frame.size.height = targetSize.height
widthConstraint.isActive = false
header.translatesAutoresizingMaskIntoConstraints = true
tableView.tableHeaderView = header
Wait viewDidLayoutSubviews() to get the actual size of the view.
If your content is static, simply set its height:
let header = HeaderView()
header.frame.size.height = 30
tableView.tableHeaderView = header
Note that the header's autoresizingMask should not contain flexibleHeight (check your xib). The header should keep the height specified.
You can give lower priority to the bottom spacing constraint and higher priority to height constraint
Related
TL;DR
I want to replace a custom (different from other items) width item in UIStackView with flexible width item and center all UIStackView items.
More info:
I have a UIStackView that holds few custom UIView's:
self.handleButtonStack.axis = .horizontal
self.handleButtonStack.alignment = .center
self.handleButtonStack.distribution = .fillProportionally
self.handleButtonStack.spacing = 10.0
let hbVideo = HandleButton(image: "icon", title: "", type: .video, delegate: self)
hbVideo.widthAnchor.constraint(equalToConstant: 50).isActive = true
let hbInstagram = HandleButton(image: "icon", title: "", type: .instagram, delegate: self)
hbInstagram.widthAnchor.constraint(equalToConstant: 50).isActive = true
let hbWhatsApp = HandleButton(image: "icon", title: "", type: .whatsapp, delegate: self)
hbWhatsApp.widthAnchor.constraint(equalToConstant: 50).isActive = true
let hbHints = HandleButton(image: "icon", title: "title", type: .hint, delegate: self)
hbHints.widthAnchor.constraint(greaterThanOrEqualToConstant: 100).isActive = true
self.handleButtonStack.addArrangedSubview(hbVideo)
self.handleButtonStack.addArrangedSubview(hbInstagram)
self.handleButtonStack.addArrangedSubview(hbWhatsApp)
self.handleButtonStack.addArrangedSubview(hbHints)
After the user has preformed some action I want to change the UIStackView and remove the hbHints button and center the items.
I do that in this way:
if let subviews = self.handleButtonStack.arrangedSubviews as? [HandleButton] {
if let hintsButton = subviews.last {
self.handleButtonStack.removeFully(view: hintsButton)
let leadingSpacer = self.createSpacer(width: 50)
let trailingSpacer = self.createSpacer(width: 50)
self.handleButtonStack.insertArrangedSubview(leadingSpacer, at: 0)
self.handleButtonStack.insertArrangedSubview(trailingSpacer, at: subviews.count)
}
}
And adding a spacer like that:
func createSpacer(width: CGFloat) -> UIView {
let space = UIView(frame: .zero)
space.backgroundColor = .red
space.translatesAutoresizingMaskIntoConstraints = false
if width != 0 {
space.widthAnchor.constraint(equalToConstant: width).isActive = true
}
return space
}
My problem is that the Constraints are breaking with error and I can't figure out why. Is it possible to add a flexible width as spacer that stretch as I put it in place?
What I already tried:
Set a contentHuggingPriority to the items
Set a contentCompressionResistancePriority to the items
Adding constraints to the spacer item
Removing the width constraint for the spacer item
No success.
Here is the constraints breaking log:
[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:0x283414050 H:[UIStackView:0x124599e30]-(0)-| (active, names: '|':UIView:0x1245e9f20 )>",
"<NSLayoutConstraint:0x2834142d0 H:|-(0)-[UIStackView:0x124599e30] (active, names: '|':UIView:0x1245e9f20 )>",
"<NSLayoutConstraint:0x283416e90 UILayoutGuide:0x282e94460'UIViewSafeAreaLayoutGuide'.trailing == UIView:0x1245e9f20.trailing + 40 (active)>",
"<NSLayoutConstraint:0x283416620 UIView:0x1245e9f20.leading == UILayoutGuide:0x282e94460'UIViewSafeAreaLayoutGuide'.leading + 40 (active)>",
"<NSLayoutConstraint:0x283428b90 MyApp.HandleButton:0x124589460.width == 50 (active)>",
"<NSLayoutConstraint:0x283428af0 MyApp.HandleButton:0x124589e40.width == 50 (active)>",
"<NSLayoutConstraint:0x283428a50 MyApp.HandleButton:0x124589610.width == 50 (active)>",
"<NSLayoutConstraint:0x2834281e0 'UISV-canvas-connection' UIStackView:0x124599e30.leading == UIView:0x124576f20.leading (active)>",
"<NSLayoutConstraint:0x283428230 'UISV-canvas-connection' H:[UIView:0x1245897c0]-(0)-| (active, names: '|':UIStackView:0x124599e30 )>",
"<NSLayoutConstraint:0x2834282d0 'UISV-fill-proportionally' UIView:0x124576f20.width == 0 (active)>",
"<NSLayoutConstraint:0x28342bc50 'UISV-fill-proportionally' UIView:0x1245897c0.width == 0 (active)>",
"<NSLayoutConstraint:0x283428280 'UISV-spacing' H:[UIView:0x124576f20]-(10)-[MyApp.HandleButton:0x124589460] (active)>",
"<NSLayoutConstraint:0x28342acb0 'UISV-spacing' H:[MyApp.HandleButton:0x124589460]-(10)-[MyApp.HandleButton:0x124589e40] (active)>",
"<NSLayoutConstraint:0x28342af80 'UISV-spacing' H:[MyApp.HandleButton:0x124589e40]-(10)-[MyApp.HandleButton:0x124589610] (active)>",
"<NSLayoutConstraint:0x28342b2a0 'UISV-spacing' H:[MyApp.HandleButton:0x124589610]-(10)-[UIView:0x1245897c0] (active)>",
"<NSLayoutConstraint:0x283429810 'UIView-Encapsulated-Layout-Width' MyApp.AngleColorsView:0x124599fc0.width == 414 (active)>",
"<NSLayoutConstraint:0x283415f90 'UIViewSafeAreaLayoutGuide-left' H:|-(0)-[UILayoutGuide:0x282e94460'UIViewSafeAreaLayoutGuide'](LTR) (active, names: '|':MyApp.AngleColorsView:0x124599fc0 )>",
"<NSLayoutConstraint:0x283416440 'UIViewSafeAreaLayoutGuide-right' H:[UILayoutGuide:0x282e94460'UIViewSafeAreaLayoutGuide']-(0)-|(LTR) (active, names: '|':MyApp.AngleColorsView:0x124599fc0 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x283428a50 MyApp.HandleButton:0x124589610.width == 50 (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.
Here you need not give any centre alignment. As per your requirement you don't need that I think as you are giving constraints for all of your views and for the last view you are also giving greaterThanOrEqual constraint which automatically stretches your view to fill up the gaps.
So try changing the alignment from .center to .fill.
Then after you delete your last view you don't have to add any empty spacer to fill up the missing fields. Instead you can give constraints for your stack view itself.
For the leading and trailing anchor of the stack view give greaterThanOrEqualTo constraint instead of equal and also add a centre aligned constraint to the stack view.
So when you remove the view now the stack view automatically arranges the view for you in your needed centre aligned position.
Hope this is your expected end result.
expected output in GIF
I have a UIViewController containing a scrollView: the scrollView is pinned (0,0,0,0) to the superview.
The scrollView contains a Content View with the following constraints set:
Inside this view, I put a square image view: it is pinned this way and its height equals the width of its superview.
Anything I described until now is done manually in the storyboard.
Then, using a simple button (so, after viewDidLoad, viewDidLayoutSubviews, etc.), I execute the following function (that 375 is currently hard-coded, but it is the heigth of the image view frame on the device I’m using for testing purposes):
var startH = 0
for i in 0...10 {
let v = UIView(frame: CGRect(x: 0, y: 375+startH, width: 375, height: startH))
v.backgroundColor = .random
contentView.addSubview(v)
startH += 100
}
let scrollerLayoutGuide = scrollView.contentLayoutGuide
scrollerLayoutGuide.heightAnchor.constraint(equalToConstant: CGFloat(startH+375)).isActive = true
scrollView.contentSize = contentView.frame.size
This should (and actually it does) create 11 views under the imageView, inside the contentView of the scrollView.
Problem is when I execute this function I get the following error:
[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:0x6000019d7d40 UIView:0x7fe66940aa30.height == UIScrollView:0x7fe66985b400.height (active)>",
"<NSLayoutConstraint:0x6000019d7d90 V:|-(0)-[UIView:0x7fe66940aa30] (active, names: '|':UIScrollView:0x7fe66985b400 )>",
"<NSLayoutConstraint:0x6000019d7de0 V:[UIView:0x7fe66940aa30]-(0)-| (active, names: '|':UIScrollView:0x7fe66985b400 )>",
"<NSLayoutConstraint:0x6000019e4690 UILayoutGuide:0x6000003c81c0'UIViewSafeAreaLayoutGuide'.bottom == UIScrollView:0x7fe66985b400.bottom (active)>",
"<NSLayoutConstraint:0x6000019e4730 UIScrollView:0x7fe66985b400.top == UILayoutGuide:0x6000003c81c0'UIViewSafeAreaLayoutGuide'.top (active)>",
"<NSLayoutConstraint:0x6000019e11d0 _UIScrollViewLayoutGuide:0x6000003ac1c0'UIScrollView-contentLayoutGuide'.height
== 1475 (active)>",
"<NSLayoutConstraint:0x6000019e9540 'UIView-Encapsulated-Layout-Height' UIView:0x7fe66950bdb0.height == 667 (active)>",
"<NSLayoutConstraint:0x6000019e45f0 'UIViewSafeAreaLayoutGuide-bottom' V:[UILayoutGuide:0x6000003c81c0'UIViewSafeAreaLayoutGuide']-(0)-| (active, names: '|':UIView:0x7fe66950bdb0 )>",
"<NSLayoutConstraint:0x6000019e4550 'UIViewSafeAreaLayoutGuide-top' V:|-(20)-[UILayoutGuide:0x6000003c81c0'UIViewSafeAreaLayoutGuide'] (active, names: '|':UIView:0x7fe66950bdb0 )>" )
Will attempt to recover by breaking constraint <NSLayoutConstraint:0x6000019d7de0 V:[UIView:0x7fe66940aa30]-(0)-| (active, names: '|':UIScrollView:0x7fe66985b400 )>
Problem is I can't understand what constraint is causing this issue and, most of all, why. Could you help me?
There is conflict between your constraints with contentView
1. There is Top, bottom, leading, trailing with the scrollview
2. Fixed height and fixed width constraint of contentView
These two will conflict each other as OS will not be sure which constraint to fulfil.
As a solution reduce the priority of height and width constraint so that the more priority is given to the constraint with respect to the scrollView.
For more details please follow below tutorial
How to configure a UIScrollView with Auto Layout
I've defined my flow layout as follows
internal lazy var layout: UICollectionViewFlowLayout = {
let layout = UICollectionViewFlowLayout()
layout.minimumLineSpacing = 16
layout.sectionInset = UIEdgeInsets(top: layout.minimumLineSpacing, left: layout.minimumLineSpacing , bottom: layout.minimumLineSpacing , right: layout.minimumLineSpacing )
layout.estimatedItemSize = CGSize(width: UIScreen.main.bounds.size.width - (layout.sectionInset.left + layout.sectionInset.right), height: 10)
return layout
}()
In the cell then I set the height for the expected content
override open func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
setNeedsLayout()
layoutIfNeeded()
let size = contentView.systemLayoutSizeFitting(layoutAttributes.size)
var newFrame = layoutAttributes.frame
newFrame.size.height = ceil(size.height)
layoutAttributes.frame = newFrame
return layoutAttributes
}
And it works. I get the cells in the height that I expect them to be, but there is a nasty warning in the console coming up for each cell
[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:0x600003c1e490 V:|-(0)-[UIView:0x7fdc8bead5d0] (active, names: '|':VLCContentCollectionViewCell:0x7fdc8becf8e0 )>",
"<NSLayoutConstraint:0x600003c1ec60 V:[UIView:0x7fdc8bead5d0]-(0)-| (active, names: '|':VLCContentCollectionViewCell:0x7fdc8becf8e0 )>",
"<NSLayoutConstraint:0x600003c4bb60 V:|-(0)-[VLAsyncImageView:0x7fdc8bea20a0] (active, names: '|':UIView:0x7fdc8bead5d0 )>",
"<NSLayoutConstraint:0x600003c43070 V:[VLAsyncImageView:0x7fdc8bea20a0]-(0)-| (active, names: '|':UIView:0x7fdc8bead5d0 )>",
"<NSLayoutConstraint:0x600003c5f340 VLAsyncImageView:0x7fdc8bea20a0.height == 100 (active)>",
"<NSLayoutConstraint:0x600003f8cb90 'UIView-Encapsulated-Layout-Height' VLCContentCollectionViewCell:0x7fdc8becf8e0.height == 10 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600003c5f340 VLAsyncImageView:0x7fdc8bea20a0.height == 100 (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.
Im pretty sure that it is because of this constraint 'UIView-Encapsulated-Layout-Height' which holds the value for the expected item size of the flow layout, because if I set that to 100 the log message doesn't show up.
However, I'm looking for dynamic cell height, so even if I set it to 100 it will fail at other places.
So my question is if I'm doing something wrong in defining my dynamic cells? Or is there maybe a way to reduce the priority of the estimated cell height, so that it will brake that constraint in case?
I'm trying to add an arbitrary amount of view from nibs into a UIStackView. The issue is that, say, if only include one view, that view grows to fill the entire stackview, instead of maintaining the proper width. Here's my code so far:
friendStackView.autoresizingMask = .flexibleWidth
friendStackView.translatesAutoresizingMaskIntoConstraints = false
let friendView = Bundle.main.loadNibNamed("FriendView", owner: self, options: nil)?.first as! FriendViewController
friendStackView.addArrangedSubview(friendView)
friendView.heightAnchor.constraint(equalToConstant: 150).isActive = true
friendView.widthAnchor.constraint(equalToConstant: 120).isActive = true
It results in the following debug:
[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:0x14eb9eb0 UIStackView:0x14ee6ed0.width == 500 (active)>",
"<NSLayoutConstraint:0x14ef83f0 XXX.FriendViewController:0x14ef2090.width == 120 (active)>",
"<NSLayoutConstraint:0x14def090 'UISV-canvas-connection' UIStackView:0x14ee6ed0.leading == XXX.FriendViewController:0x14ef2090.leading (active)>",
"<NSLayoutConstraint:0x14def230 'UISV-canvas-connection' H:[XXX.FriendViewController:0x14ef2090]-(0)-| (active, names: '|':UIStackView:0x14ee6ed0 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x14ef83f0 XXX.FriendViewController:0x14ef2090.width == 120 (active)>
You have a conflict here the stackView width = 500 and you're trying to give the subview which is supposed to fill the whole width 120
"<NSLayoutConstraint:0x14eb9eb0 UIStackView:0x14ee6ed0.width == 500 (active)>",
"<NSLayoutConstraint:0x14ef83f0 XXX.FriendViewController:0x14ef2090.width == 120
I have a stack view that look like the figure below:
So I change the height of the image programmatically to make it fit the image that download from my server,if dont have image,the height constraints of image will set to be zero.
Here is my code to doing so:
let imageUrl = URL(string :imageString)
if let data = try? Data(contentsOf: imageUrl!)
{
guard let actualImage: UIImage = UIImage(data: data) else{
print("No image!")
ImageView.image = nil
defaultImageHeightContrainst = ImageHeightContrainst.constant
ImageHeightContrainst.constant = 0
layoutIfNeeded()
return
}
let imageHeight = actualImage.size.height * actualImage.scale
print("imageHeight = \(imageHeight)")
defaultImageHeightContrainst = ImageHeightContrainst.constant
ImageHeightContrainst.constant = imageHeight
layoutIfNeeded()
//here display the image to the imageview
ImageView.kf.setImage(with: imageUrl)
}
With the code above,the image height is scale according to actual image height which download from internet.If dont have image,the "image" part also set to 0 already.
This is what I expected,but now I face an error below whenever the "image" height become taller in order to fit the actual image height
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:0x6080002868b0 UIImageView:0x7f9cbae59240.height == 50 (active)>",
"<NSLayoutConstraint:0x608000286bd0 UIView:0x7f9cbae5ad80.height == 1 (active)>",
"<NSLayoutConstraint:0x608000286d10 UIImageView:0x7f9cbae5b440.height == 458 (active)>",
"<NSLayoutConstraint:0x608000286f90 UIView:0x7f9cbae5bb50.height == 1 (active)>",
"<NSLayoutConstraint:0x6080002871c0 V:|-(0)-[UILabel:0x7f9cbae5b160] (active, names: '|':UIStackView:0x7f9cbae5af60 )>",
"<NSLayoutConstraint:0x608000287350 V:[UILabel:0x7f9cbae5b160]-(10)-[UIImageView:0x7f9cbae5b440] (active)>",
"<NSLayoutConstraint:0x6080002873a0 V:[UIImageView:0x7f9cbae5b440]-(10)-[UIStackView:0x7f9cbae5b670] (active)>",
"<NSLayoutConstraint:0x608000287580 V:[UIStackView:0x7f9cbae5b670]-(10)-[UIView:0x7f9cbae5bb50] (active)>",
"<NSLayoutConstraint:0x6080002875d0 V:[UIStackView:0x7f9cbae5c0f0]-(0)-| (active, names: '|':UIStackView:0x7f9cbae5af60 )>",
"<NSLayoutConstraint:0x608000287670 V:[UIView:0x7f9cbae5bb50]-(10)-[UIStackView:0x7f9cbae5c0f0] (active)>",
"<NSLayoutConstraint:0x6080002877b0 V:|-(10)-[UIImageView:0x7f9cbae59240] (active, names: '|':UITableViewCellContentView:0x7f9cbae5a0c0 )>",
"<NSLayoutConstraint:0x6080002878f0 V:[UIImageView:0x7f9cbae59240]-(8)-[UIView:0x7f9cbae5ad80] (active)>",
"<NSLayoutConstraint:0x6080002879e0 V:[UIStackView:0x7f9cbae5af60]-(10)-| (active, names: '|':UITableViewCellContentView:0x7f9cbae5a0c0 )>",
"<NSLayoutConstraint:0x608000287a80 V:[UIView:0x7f9cbae5ad80]-(8)-[UIStackView:0x7f9cbae5af60] (active)>",
"<NSLayoutConstraint:0x608000288c00 'UISV-canvas-connection' UIStackView:0x7f9cbae5c0f0.top == _UILayoutSpacer:0x6080001cd5c0'UISV-alignment-spanner'.top (active)>",
"<NSLayoutConstraint:0x608000288ca0 'UISV-canvas-connection' V:[_UILayoutSpacer:0x6080001cd5c0'UISV-alignment-spanner']-(0)-| (active, names: '|':UIStackView:0x7f9cbae5c0f0 )>",
"<NSLayoutConstraint:0x608000289970 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7f9cbae5a0c0.height == 476.5 (active)>"
)
Before asking,I already checked all my other constraints,which is all set correctly.I even disable all the code that can change the height of "image",once disable,there is no problem.The error only occurred when I intend to change the height.
I even tried to add ImageView.translatesAutoresizingMaskIntoConstraints = false before layoutIfNeeded(),but the error is still exist.
So what is the correct way to change the height of image in order to fit the actual image download from server?
Considering that the last constraint says
"<NSLayoutConstraint:0x608000289970 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7f9cbae5a0c0.height == 476.5 (active)>"
I assume you are using stackView inside of a UITableViewCell to implement automatic height cells in a tableView. If my assumption is correct, then the problem is not with the stackView, nor with the imageView, but with the way UITableView works with UITableViewAutomaticDimension and Autolayout. If the layout works as you expect, and the warning is the only thing that bugs you, then read following.
Therefore it seems to me that this is a result of an known "bug" - there is a collision of the height set by the tableView and the height calculated by the autolayout. When rendering the cell, the tableView first applies the default height, calculates the autolayout height, and then use the latter - at least it seems so. See my question. The constraint mentioned above ('UIView-Encapsulated-Layout-Height') is the one applied by the UITableView that later goes away.
That means that the constraints you are using are probably OK. Just set one of the constraints defining height to priority = 999 (so that until it deactivates the default height constraint it won't cause any conflict). In the end, it will result in using your constraint anyway, so it will not cause any layout trouble.
E.g., if you constrain the stackView to fit the cell's contentView, set the stackView.bottomAnchor to contentView.bottomAnchor just with the priority set to 999. If you did the layout programmatically, this might be your solution:
let bottomConstraint = tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
bottomConstraint.priority = UILayoutPriority(rawValue: 999)
NSLayoutConstraint.activate([
// rest of the constraints
stackView.topAnchor.constraint(equalTo: contentView.topAnchor),
stackView.leftAnchor.constraint(equalTo: contentView.leftAnchor),
stackView.rightAnchor.constraint(equalTo: contentView.rightAnchor),
bottomConstraint,
])
If you do the layout in storyboards, just select appropriate constraint in the storyboards, and in the attributes inspector set its priority to 999 (for example):