Dynamic Height Table Cell with Autolayout and UITableAutomaticDimension (Dynamic UILabel + several UIImageViews) - ios

I looked through the articles related with dynamic table cell and auto layout for 3 days and not working so far.
Below is the table cell what I wanted. Here the main issue is UILabel for post text and UIImages.
Here is the hierarchy of the UI elements.
- Content View
+ ...
+ UILabel for text - dynamic height
+ UIView - image view container
* UIImageView
* UIImageView
* ....
Label has line break mode wrap text and lines set to 0.
Label and the container view has constraints for top, bottom, leading and trailing. ImageViews are added at runtime and has constraint for top, leading, trailing, bottom and height constraints.
First image view has top constraint to container view and last image view has bottom constraint to container view and others has top constraint to upper image view.
When the table is first loaded (cells has different image counts), it looks fine, but when I scroll up and down, constraints are breaking in some cells and images are overlapping inside cells.
Here is the error output:
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:0x17428aaf0 V:|-(0)-[UIImageView:0x14be77ed0] (active, names: '|':UIView:0x14be75b20 )>",
"<NSLayoutConstraint:0x17428a6e0 UIImageView:0x14be77ed0.height == 160 (active)>",
"<NSLayoutConstraint:0x17428acd0 UIImageView:0x14be77ed0.bottom == UIView:0x14be75b20.bottom (active)>",
"<NSLayoutConstraint:0x174289650 V:|-(0)-[UIImageView:0x14be43ce0] (active, names: '|':UIView:0x14be75b20 )>",
"<NSLayoutConstraint:0x17428bb80 UIImageView:0x14be43ce0.height == 160 (active)>",
"<NSLayoutConstraint:0x17428be50 V:[UIImageView:0x14be43ce0]-(10)-[UIImageView:0x14be74b10] (active)>",
"<NSLayoutConstraint:0x17428bfe0 UIImageView:0x14be74b10.height == 160 (active)>",
"<NSLayoutConstraint:0x17428c080 UIImageView:0x14be74b10.bottom == UIView:0x14be75b20.bottom (active)>"
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x17428be50 V:[UIImageView:0x14be43ce0]-(10)-[UIImageView:0x14be74b10] (active)>
Please help me with this issue. Thank you.

To make sure the stack view does not contain old images when the cell is dequeued, you need to clean it in prepareForReuse():
override func prepareForReuse() {
super.prepareForReuse()
stack.arrangedSubviews.forEach {
stack.removeArrangedSubview($0)
$0.removeFromSuperview()
}
}

I would suggest not to give your images height, instead add a vertical stackview into your container view and add all your images in there. make sure they have content mode set to aspect fit and the stackview should take care of the rest. don't forget to constrain the stackview to the bottom of the label and the bottom of the cell, so it knows how much space it has. it will take care of your images by itself

ImageViews are added at runtime and has constraint for top, leading, trailing, bottom and height constraints.
This is your error message. Remove either height or one of the constraint that you choose either bottom or top contraint. You can not have all 4 sides constrained and add a height constrant to that.
Sidenote:
That goes same for width, if you set a width constraint, you can not have both sides leading/trailing constrained at the same time.
EDIT:
Also, easier off with using a UIStackView as suggested in the comments sections.

Related

"Unable to simultaneously satisfy constraints" with UITableViewCell

I used the Interface Builder to create a pretty simple layout inside a UITableViewCell for my Xcode 13.0/Swift 5/iOS 13.5 app:
UIStackView (with 2 UIViews and UILabels inside) at the top and a UIView (with a UIImageView inside) below it.
The exact constraints are currently:
UIStackView: 10pts leading, 10pts trailing, 0pts top, 10pts to the UIView at the bottom, height of 50pts
UIView: 20pts leading, 20pts trailing, 10pts bottom, (10pts top from the UIStackView), height=width
UIImageView inside the UIView: 0pts leading/trailing/top/bottom, align center x to Superview (=UIView)
Contrary to other questions about the warning here on stackoverflow I don't set the UITableViewCell's height directly but want it to be set by its content. The UIImageView's image is set at runtime and should keep its shape, so square images should be square and the other rectangular images should be centered horizontally (-> invisible bars left/right, if necessary) but not vertically.
Xcode doesn't complain about missing constraints but this layout keeps giving me the infamous "Unable to simultaneously satisfy constraints" warning.
[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:0x600002d22d50 UIStackView:0x7fe4fa293330.height == 50 (active)>",
"<NSLayoutConstraint:0x600002d22df0 UIView:0x7fe4fa29d1c0.height == UIView:0x7fe4fa29d1c0.width (active)>",
"<NSLayoutConstraint:0x600002d23070 V:|-(0)-[UIStackView:0x7fe4fa293330] (active, names: '|':UITableViewCellContentView:0x7fe4fa2840f0 )>",
"<NSLayoutConstraint:0x600002d23110 H:[UIView:0x7fe4fa29d1c0]-(20)-| (active, names: '|':UITableViewCellContentView:0x7fe4fa2840f0 )>",
"<NSLayoutConstraint:0x600002d23160 V:[UIStackView:0x7fe4fa293330]-(10)-[UIView:0x7fe4fa29d1c0] (active)>",
"<NSLayoutConstraint:0x600002d231b0 H:|-(20)-[UIView:0x7fe4fa29d1c0] (active, names: '|':UITableViewCellContentView:0x7fe4fa2840f0 )>",
"<NSLayoutConstraint:0x600002d23200 V:[UIView:0x7fe4fa29d1c0]-(10)-| (active, names: '|':UITableViewCellContentView:0x7fe4fa2840f0 )>",
"<NSLayoutConstraint:0x600002d36530 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7fe4fa2840f0.height == 325.5 (active)>",
"<NSLayoutConstraint:0x600002d364e0 'UIView-Encapsulated-Layout-Width' UITableViewCellContentView:0x7fe4fa2840f0.width == 295 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600002d22df0 UIView:0x7fe4fa29d1c0.height == UIView:0x7fe4fa29d1c0.width (active)>
I already checked with wtfautolayout.com but the only thing wrong that I can see is the height: If the width is 295, then the height should be exactly 50+10+295-40+10=325 (UIStackView.height + constraint in-between + UIView.width - leading/trailing constraints + bottom constraint), not 325.5. Everything else looks fine to me, so I'm not sure why it would calculate that wrong height (and if that's even the problem).
I already tried a couple of things:
Added the UIStackView's fixed height (didn't use it before everything looked fine and it didn't complain about it, still got the warning though)
UIView.width = UIImageView.height (1:1 aspect ratio, instead of the one above)
UIImageView.width = UIImageView.height (1:1 aspect ratio, instead of the one above)
Removed the "center x" constraint
Nothing worked, I keep getting the constraint warning and if it doesn't show up in portrait mode because of something I changed, then it does as soon as I switch to landscape mode. How do I fix this in IB/without code?
Try changing the priority of the height=width constraint to High instead of Required

Unable to simultaneously satisfy constraints When trying to load xib file

I am trying to implement the UITableView using xib file
But when I run the app I am getting the following error & the xib is properly in small screen like iPhone4s
it works fine in larger display size.
Screenshot of xib
Any help will be appreciated
Error
2016-12-14 17:12:41.826 FoodStrock[5776:1761262] 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:0x7fcc2a6dfac0 V:[UIImageView:0x7fcc2a6e1010(63)]>",
"<NSLayoutConstraint:0x7fcc2a617530 V:[UIImageView:0x7fcc2a6e1010]-(8)-| (Names: '|':UITableViewCellContentView:0x7fcc2a6e1270 )>",
"<NSLayoutConstraint:0x7fcc2a6cc3b0 V:|-(9)-[UIImageView:0x7fcc2a6e1010] (Names: '|':UITableViewCellContentView:0x7fcc2a6e1270 )>",
"<NSLayoutConstraint:0x7fcc2a4955a0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fcc2a6e1270(59.6667)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7fcc2a6dfac0 V:[UIImageView:0x7fcc2a6e1010(63)]>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2016-12-14 17:12:41.827 FoodStrock[5776:1761262] 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:0x7fcc2a6a69d0 V:[UILabel:0x7fcc2a6e1670'Address'(63)]>",
"<NSLayoutConstraint:0x7fcc2a693820 UILabel:0x7fcc2a6e1670'Address'.bottom == UITableViewCellContentView:0x7fcc2a6e1270.bottomMargin>",
"<NSLayoutConstraint:0x7fcc2a6e0c00 UILabel:0x7fcc2a6e1670'Address'.top == UITableViewCellContentView:0x7fcc2a6e1270.topMargin + 1>",
"<NSLayoutConstraint:0x7fcc2a4955a0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fcc2a6e1270(59.6667)]>"
)
Put your UIImageView , UILabel, UIButton in single UIView(says mainView). Now mainView constraints will be leading, trailing, top bottom from the xib view(superView). Now constraints of UIImageView , UILabel, UIButton is according to your requirement w.r.t. mainView.
NOTE: Give constraints to the UIComponents as minimal as possible but keep mind about it full fills your requirement. Like here, give constraints like this:
UIImage : top, bottom , Leading wrt mainView and constant width or you can give horizontally center to container, leading, height, width.
UIButton : top, bottom, trailing wrt mainView and constant width or you can give horizontally center to container, leading, height, width.
UILabel : leading trailing and horizontally centre to container is enough but you can give height also.
UILabel can automatically take height and width according to the text font size you just need to specify x and y coordinates.

Single UIImageView in UITableViewCell using Autolayout

I'm trying to place a UITableViewCell containing a single UIImageView in a UITableView using dynamic cell heights with AutoLayout (i.e. tableView.rowHeight = UITableViewAutomaticDimension).
The images I will be displaying have a specific ratio (1000:667), but there are other cells besides the image cells. I've built my constraint logic for this cell to respect the Aspect Ratio of the UIImageView.
Therefore, to avoid malformation or parts of the image not being shown (clip subviews) the aspect ratio constraint should determine the cell's height depending on the device screen width.
The cell was built in a Nib file with the following constraints:
Apparently this works, since the cell's height is set accordingly on runtime depending on the device (simulator) used.
The problem is I get lots of breaking constraint error logs (below). Any ideas why iOS/the table view complaints about this constraints?
Suggestions on different approaches to displaying a UITableViewCell that respects the aspect ratio would be appreciated too.
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:0x7ff5097a7910 UIImageView:0x7ff5097393a0.width == 1.49925*UIImageView:0x7ff5097393a0.height>",
"<NSLayoutConstraint:0x7ff509739550 V:|-(0)-[UIImageView:0x7ff5097393a0] (Names: '|':UITableViewCellContentView:0x7ff5097a8e10 )>",
"<NSLayoutConstraint:0x7ff5097aa180 UIImageView:0x7ff5097393a0.centerY == UITableViewCellContentView:0x7ff5097a8e10.centerY>",
"<NSLayoutConstraint:0x7ff5097a8c70 H:|-(0)-[UIImageView:0x7ff5097393a0] (Names: '|':UITableViewCellContentView:0x7ff5097a8e10 )>",
"<NSLayoutConstraint:0x7ff5097a8cc0 H:[UIImageView:0x7ff5097393a0]-(0)-| (Names: '|':UITableViewCellContentView:0x7ff5097a8e10 )>",
"<NSLayoutConstraint:0x7ff5097b6440 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7ff5097a8e10(276)]>",
"<NSLayoutConstraint:0x7ff5097b4930 'UIView-Encapsulated-Layout-Width' H:[UITableViewCellContentView:0x7ff5097a8e10(414)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7ff5097a7910 UIImageView:0x7ff5097393a0.width == 1.49925*UIImageView:0x7ff5097393a0.height>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
This one cause b'cos u gave unnecessary autolayouts (height, width and center y) conflits.
eg. you gave height then top and bottom, height is fixed still you gave top and bottom alignment... that's unnecessary...
you can try this suggestions.
1)center y + Trailing + Leading + Height.
2)Top + Bottom + Trailing + Leading.
3)height + width + center y + Leading
and many more
I hope you understand...
Fdo, the logs that you have posted clearly explains what is going wrong in there :)
What is the issue?
You have aspect ratio being set on imageView. As a result imageView will try to resize itself on assigning the image, while maintaining the aspect ratio that you have specified. So ImageView's height and width can/may vary depending on the image that you are assigning.
You have applied trailing and leading space constraint from imageView to the cell's contentView. That means no matter what happens you want the image view to cover the entire width of the cell. You are conflicting with your own constraint. Just above you said imageView is free to change its frame now you are saying it should cover whole width of cell how is that even possible buddy?
Similarly, you applied top and bottom constraint on image view to the cell's contentView. Now why is that not breaking then? Simple because cells height is dynamically being calculated based on the image you pass to imageView. So obviously the imageView's size after resizing will be equal to the height of cell. So no issue with cell height.
How to solve ?
Simple remove trailing and leading space constraint on imageView to cell's contentView and instead apply horizontally centre constraint on imageView that will give imageViews x position as well and will not mess with the width of imageView. Hence no constraints breaks and everything will work like charm
Extra piece of advice
When you have specified that imageView will have top and bottom constraint to cells content view which means that imageView height will always be equal to the cell's height, dude does it seriously make any sense to say that imageView will be at vertically centre of cell? Because anyway your imageView will cover the whole cell top to bottom.Any way it won't break anything but passing constraints more than what is actually needed is not the best thing to do as it might result in other consequences in future.
Hope it helps.
For autolayouting any view, only thing required to be satisfied is all views should get width, height,and x and y positions.
Now from your question, it looks that out of 6 constraints that you provided, only last 4 constaints are self sufficient to complete the requirements, so first 2 constraints are not required. Just remove them. All things will be fine.
The warning messages you are seeing is due to more than 2 constraints that you provided confuses system to take which out of them.

CollectionViewCell, custom cell, autolayout constraints with multiline

I have storyboard with custom cell, I have 3 views on my custom cell but one of the view causing a problem, UILabel with 2 line support. I use W:Any-H:Any and create a constraits to a label like this (now, to elimiate all the issues - i'm connecting it to superviews, not to views nearest, but error still occurs):
Leading Space to Superview
Trailing Space to Superview
Top Space to Superview
So it looks like this:
If I remove constraints from this view I'm not getting error so error must be from this.
And then i get constraints error:
(
"<NSLayoutConstraint:0x7fe1d3df4e80 UILabel:0x7fe1d3df7730'Autos, Roller, Fahrr\U00e4der,...'.trailing == UIView:0x7fe1d7a33140.trailingMargin>",
"<NSLayoutConstraint:0x7fe1d3df4ed0 H:|-(70)-[UILabel:0x7fe1d3df7730'Autos, Roller, Fahrr\U00e4der,...'] (Names: '|':UIView:0x7fe1d7a33140 )>",
"<NSAutoresizingMaskLayoutConstraint:0x7fe1d3dbb1c0 h=--& v=--& H:[UIView:0x7fe1d7a33140(50)]>"
)
What's the problem and how to fix it?
Changing the priority of Trailing Space to 999 is a simple workaround, but I cannot explain how this fixes that.
It appears that Trailing Space (1st constraint in the error) constraint conflicts with constraint which is translated from the autoresizing mask of contentView (3rd constraint) and this workaround resolves it.

UIScrolView auto layout contraints breaking on device rotation

I'm having a rather annoying problem with auto-layout constraints set on a UIScrollView and its sub views. When the device orientation changes, it breaks a constraint with the following warning:
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:0x7a1b1830 V:[UIView:0x7a1b0520(768)]>",
"<NSLayoutConstraint:0x7a1c5990 V:[UIView:0x7a1bcf50(1024)]>",
"<NSLayoutConstraint:0x7a17aa70 V:|-(0)-[UIView:0x7a1b0520] (Names: '|':UIScrollView:0x7a176520 )>",
"<NSLayoutConstraint:0x7a1c49c0 V:[UIView:0x7a1b0520]-(0)-| (Names: '|':UIScrollView:0x7a176520 )>",
"<NSLayoutConstraint:0x7a172620 V:[UIView:0x7a1bcf50]-(0)-| (Names: '|':UIScrollView:0x7a176520 )>",
"<NSLayoutConstraint:0x7a172650 V:|-(0)-[UIView:0x7a1bcf50] (Names: '|':UIScrollView:0x7a176520 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7a1c5990 V:[UIView:0x7a1bcf50(1024)]>
I've set up a scroll view in my storyboard and it contains two containers as sub views. The scroll view itself is pinned on all four sides to the superview (Editor/Pin/Leading-, Trailing-, Top-, Bottom-Space to superview). The two containers have their edges pinned to the scroll view with Auto-Layout constraints but the width & height of both is set as fixed on the storyboard, see att. image:
The width and height of the two containers gets updated via code, once initially in viewDidLoad() and whenever the devices orientation changes, in didRotateFromInterfaceOrientation():
_primaryWidth.constant = view.bounds.size.width
_primaryHeight.constant = view.bounds.size.height
_secondaryWidth.constant = _primaryWidth.constant - 200
_secondaryHeight.constant = _primaryHeight.constant
This is when the above warning appears and the constraints break and the layout goes overboard. Can somebody tell me why this is happening and how to fix it?
(Note the minus 200. This is because the right container should have a smaller width. But it doesn't affect the issue. The constraints break even without this.)
You have constraints which pin the edges of the scroll view to the edges of the screen which works in both portrait and landscape.You also have a constraint which sets the height of one of your views to 1024.
In portrait that all works, but the moment you rotate to landscape you can't have something be 1024 height pinned to the edge of the screen on top an bottom because the screen is only 768 in height. One has to go and you can see which one gets the axe.
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7a1c5990 V:[UIView:0x7a1bcf50(1024)]>
Remove the height constraints and you'll be fine. Why would you need them anyway? You want the views to pin to the edge of the screen/superview regardless of the size your given. Non-arbitrary values will also allow you to carry the same code/layout to other devices or as sub-views without layout changes.

Resources