Single UIImageView in UITableViewCell using Autolayout - ios

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.

Related

What constraints should single UIImageView have in UITableViewCell?

I just want to display UIImageView with 150 px height and 100% width of content view in UITableViewCell. I just knew that I am not able to do this, because I clearly do not understand how Auto Layout works. First of all, I gave trailing and leading constraints, because image should have full width. Ok. AutoLayout still requires constraints, because it cannot solve its inner equation. Ok, then I gave 150 px height constraint. It still requires one additional constraint. And I really do not know which constraint should I give. Let it be vertical centering constraint, but in this case my image will not appear in its own full height. Let it be bottom constraint, but it also ruins my design as top constraint. So, what is the answer?
Here is something that I cooked up on Xcode. Hope this helps.

NSLayoutConstrains error occurs when reorder the UITableViewCell

I set a simple cell in storyboard,
Thers's a imageview and a label, I set some constrains, it's imageView's leading ,top and bottom space to contentview, and the imageView's width and height, and the label's horizontal spacing to imageview and vertically center to imageview.
When I run the app, it shows correct, no error occurs.
The rightBarButtonItem is the system edit button. When I reorder the cell, constrain error occurs, I do not know how to fix it.
2015-11-11 23:08:05.681 HiPDA[10108:2305919] 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:0x7fce60ce6cf0 V:[UIImageView:0x7fce60cac370(40)]>",
"<NSLayoutConstraint:0x7fce60ce6f10 UITableViewCellContentView:0x7fce60ca0610.topMargin == UIImageView:0x7fce60cac370.top>",
"<NSLayoutConstraint:0x7fce60ce7020 UITableViewCellContentView:0x7fce60ca0610.bottomMargin == UIImageView:0x7fce60cac370.bottom - 0.5>",
"<NSLayoutConstraint:0x7fce60c03a70 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7fce60ca0610(56)]>"
)
Will attempt to recover by breaking constraint
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.
I was confused, when it showed, scrlled and removed, no errors occur, but when I reordered the cell, constrain error occurs, I do not know how to fix it. Thank you.
I upload the project, you can download here download link
There's are two navigation controllers, change the init controller between them, when the tableviewcell contains only label no error occurs, but when the tableviewcell contains imageview error occurs when reorder cell.
You gave imageView two Sets of constraints to determine it's height ,one is top&& bottom space, another is height.
When they conflicts with each other, you will get this alert.Change one of them to optional will fix the problem.
In you case ,You can change your imageView's height constraint from "=" to ">=" or lower height constraint's priority to 999.
Looking at your constraints the conflict is that
The imageview height is set to 40, it is pinned to the top and bottom of the cell, while the cell height is 56. how big do you want the imageview 40 or 56?
You can solve this by removing the top and bottom constraints and just do a center vertical to the cell constraint. i.e. ImageView.centerY = centerY
Here's modified constraints for your project on the image view

Strange autolayout behaviour on collection views

I have an issue with autolayout, the console is reporting problems with an image view I have in a cell:
RefreshCatalogue[31754:16177989] 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:0x7fa98103b740 V:[UIImageView:0x7fa9810375d0]-(0)-| (Names: '|':UIView:0x7fa9810371d0 )>",
"<NSLayoutConstraint:0x7fa98103b7e0 V:|-(0)-[UIImageView:0x7fa9810375d0] (Names: '|':UIView:0x7fa9810371d0 )>",
"<NSLayoutConstraint:0x7fa98103b8d0 UIImageView:0x7fa9810375d0.centerY == UIImageView:0x7fa981037490.centerY>",
"<NSLayoutConstraint:0x7fa98103ba60 UIImageView:0x7fa981037490.top == UIView:0x7fa9810371d0.topMargin + 71>",
"<NSAutoresizingMaskLayoutConstraint:0x7fa980d44a10 h=--& v=--& V:[UIView:0x7fa9810371d0(50)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7fa98103b8d0 UIImageView:0x7fa9810375d0.centerY == UIImageView:0x7fa981037490.centerY>
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.
The problem is that if I do:
[self.collectionView reloadItemsAtIndexPaths:#[indexPath]];
Nothing shows even tho the image view seems to have correct frame, the image property is set.
If I reload the entire collection view with:
[self.collectionView reloadData];
The error is still there but the image shows. The code is open here shall anyone be interested in taking a look:
https://github.com/Ridiculous-Innovations/RefreshCatalogue
Also, all the constraints in the story board seem to be in blue. Any idea what might be causing the issue?
Edit: Needless to say that all the elements, including the image view are on the right place (I did debug frames and set random colours) but the image didn't display till refresh ... sometimes the cells don't display at all
You have issue with UIImageView:0x7fa981037490.top == UIView:0x7fa9810371d0.topMargin + 71 and parent frame with 0 height (so imageview height must be negative, but this is not allowed), like right after calling dequeueReusableCell method.
Possible workaround for this case is change priority from 1000 to 999 on the most bottom constraint in nested view (Vertical Space - catalogueHeaderCell - Image View and Vertical Space - catalogueCell - Info View).
In second cell some constraints are disabled. that means that constraints are removed for Any Height Any Width. so when you run app in iphone than that constraints conflict with your current constraints.
so remove that highlighted disable constraints.
Try this it helps me in removing those constraint break in console.
yourCustomCell.contentView.frame = yourCustomCell.bounds;
Views:
UIView:0x7fa9810371d0, let's name it container
UIImageView:0x7fa9810375d0, let's name it image1
UIImageView:0x7fa981037490, let's name it image2.
Not let's inspect the constraints
Container height is 50, specified by autoresizing. The height is probably not specified by your collection view. Most likely this is the size of the cell when it gets created before it gets resized to the size specified by your collection view layout.
image2 is 71 points under the topMargin of container, so it is at least 21 points under bottom edge of the container.
image1 bottom is aligned with the bottom of the container, so it is above the bottom edge of the container.
Now your last constraint centers image1 and image2 vertically so there is obviously a collision.
It's a bit hard to know what you are trying to do but I suppose you should position only image1 relative to the container and the only vertical constraint for image2 should be the ones that centers them vertically.
Too see the errors in Interface Builder, change your cell height to 50, you will see everything broken up. There are just some unnecessary constraints which cause conflict on resizing.
There are also some constraints that are not installed for the current size class. It's possible that you are running the app on a simulator that is of a different size class and has them installed. That means there are even some additional collisions.
check your imageView centerY constrain
delete this constrain...
this problem is occur because of constrain ambiguity. while adding auto layout you have to apply proper auto layout constrain to imageView.
After deleting centreY constrain if there is ambiguity then xcode will again show you same error, again you have to delete ambiguous constrain.
Well the warning message gives a clue to what is wrong.
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7fa98103b8d0 UIImageView:0x7fa9810375d0.centerY == UIImageView:0x7fa981037490.centerY>
So to analyse you have two view based objects. One is set to centre its self from top to bottom to the other view (0x7fa9810375d0 to 0x7fa981037490 - these are the views id's)
But also view id 0x7fa981037490 has another constraint,
<NSLayoutConstraint:0x7fa98103ba60 UIImageView:0x7fa981037490.top == UIView:0x7fa9810371d0.topMargin + 71>
Which looks like the top of 0x7fa981037490 is being aligned to the top of view 0x7fa9810371d0 plus 71 points.
I haven't downloaded your project but I'd bet that's where the problem lies. Best guess is the centre.y constraints cannot be satisfied because the align top moves the ImageView into a place that breaks it. Try to look at what you have set in constraints visually in your head. You have aligned to ImageViews and aligned one of those to the edge of another view. How will that break? (is what you should be asking yourself)
Try removing a constraint one at a time and build and run. If the warning goes, thats the one that needs fixing. Yes the view might look weird and you can use Command + Z to undo the deletion of the constraints one by one.
Give it a go. Let me know

AutoLayout issue in dynamic UITableViewCell's subviews

While I seem to have taken the gist of setting the view constraints on UIViews of storyboards, I just can't seem to figure out why constraints are not properly working in a dynamic cell prototype ContentView's subviews.
The cell is pretty simple: A UIImageView background that fills the entire cell, in front of it another UIImage and a label as following:
The background UIImageView has the following 4 constraints:
0 fixed to: trail, bottom, top and leading space to superview
The profile picture image has a fixed width and height and a constant 13pts space to leading superview and has a vertical center in container
The Label has an 8pt leading space to the profile pic and trailing space to superview, and has a vertical center in container.
This is what I am getting:
Did I miss something? I researched the issue but no answer solved the issue. However, I tried adding the following lines in the cellForRowAtIndexPath after loading the cell:
cell.setNeedsUpdateConstraints()
cell.updateConstraintsIfNeeded()
which gave the following errors at runtime:
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:0x7fe5434852c0 H:[UIImageView:0x7fe543484450(75)]",
"NSLayoutConstraint:0x7fe5436c5cd0 H:|-(12)-[UIImageView:0x7fe543484450] (Names: '|':UITableViewCellContentView:0x7fe5434820f0 )",
"NSLayoutConstraint:0x7fe5436c34e0 H:[UILabel:0x7fe543487430'Joseph']-(8)-| (Names: '|':UITableViewCellContentView:0x7fe5434820f0 )",
"NSLayoutConstraint:0x7fe5436bcca0 H:[UIImageView:0x7fe543484450]-(8)-[UILabel:0x7fe543487430'Joseph']",
"NSLayoutConstraint:0x7fe5436cb110 'UIView-Encapsulated-Layout-Width' H:[UITableViewCellContentView:0x7fe5434820f0(0)]"
)
Will attempt to recover by breaking constraint
NSLayoutConstraint:0x7fe5434852c0 H:[UIImageView:0x7fe543484450(75)]
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.
Any clues?
Well, problem is priorities.
You have background image, which has some size according to image you put into it and than there is a profile picture with fixed height and constant space 13pts top and bottom.
Table may have separator and that one is adding extra space.
So advice: lower for example bottom 13pts constrains from 1000 to 750. That should remove warning.

How to specify square (actually round) avatar in Xcode 5 storyboard with Auto Layout on?

Is there a way in Xcode 5 to specify that an image view should be square - both in portrait and landscape orientations?
Is it possible in the Storyboard (with "Auto Layout" on) or do I have to do it in the view controller source code?
I have prepared a simple test app for iPhone. On the top it should display a round user avatar, so I am using SDWebImage and NZCircularImageView through CocoaPods.
So the avatar bounds should be square. When I set its width and height to 280 through constraints (here fullscreen),
this works - but in portrait mode only:
While in the landscape orientation this of course fails:
So I wonder if there is a trick to make it work (the avatar be perfectly round) in landscape orientation as well?
UPDATE:
When rotating to landscape, there is this warning:
2014-04-26 17:57:00.967 MyPhone[1220:60b] 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:0x8c82e10 H:[NZCircularImageView:0x8c82a70(280)]>",
"<NSLayoutConstraint:0x8c87640 H:[NZCircularImageView:0x8c82a70]-(20)-| (Names: '|':UIView:0x8c86870 )>",
"<NSLayoutConstraint:0x8c876a0 H:|-(20)-[NZCircularImageView:0x8c82a70] (Names: '|':UIView:0x8c86870 )>",
"<NSAutoresizingMaskLayoutConstraint:0x8d48410 h=--& v=--& V:[UIView:0x8c86870(480)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x8c82e10 H:[NZCircularImageView:0x8c82a70(280)]>
Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
So as suggested by Jesse I have removed the redundant constraints (to the left and right of the image view) and added horizontal alignment to keep the image view in the middle.
However I still don't know how to shrink the image view when in landscape mode - so that it doesn't overlap the 2 labels and the button on the bottom of the view:
What I am trying to achieve:
Have a round (i.e. its bounds should be square) avatar on the top
The 2 labels and the button should always be visible at the bottom
The avatar should grow to take any available space
UPDATE 2:
I've added ratio 1:1 constraint and also 20px from the image view bottom to the first name label (here fullscreen):
The landscape is ok now, exactly as I wanted it to be:
But the portrait mode is not ok: the width does not fit:
And it doesn't look good if I just add the left/right constraints:
You may pin width of your image to 280px and then ctrl drag from image view to itself and choose aspect ratio constraint with multiplier 1. This will make height of your image view match to it's width
Here's how I have done it:
Set the ratio to be 1:1.
Set horizontal right and left spacing as a >= constraint.
Set top-space as a fixed value
Set vertical spacing from the image to first label as >= constraint
Make the label fixed on the bottom
Center the image horizontally.
And heres a screenshot of my constraints, note that the fixed width is removed at build time. This is only to make IB make the square something other than 0px.
Your view is over-constrainted; you have set both the width and constraints to the left and right edges of the superview. This can't be satisfied in landscape, so you'll have to remove some constraints. (You're probably getting an error about this in the log?)
I'm not sure exactly what effect you want, but you could try removing the left and right edge constraints and instead adding a horizontal centering constraint. This will keep you view the same size in both orientations. If you want something different, try adding some more details or a mock up of the landscape layout you want.

Resources