UIView-Encapsulated-Layout-Width / Height Constrained to Zero - uitableview

There are a number of stack overflow questions about auto-layout of UITableView cells and section headers / footers that concern the UIView-Encapsulated-Layout-Width constraints that the UITableView uses to make its components be the correct size:
what is NSLayoutConstraint "UIView-Encapsulated-Layout-Height" and how should I go about forcing it to recalculate cleanly
iOS 8.3 'UIView-Encapsulated-Layout-Width' in Custom Keyboard
Auto-layout: What creates constraints named UIView-Encapsulated-Layout-Width & Height?
What is a 'UIView-Encapsulated-Layout-Width' constraint?
The purpose of these constraints seems pretty clear – they allow the UITableView and also UICollectionView to interface with constraint layout and pass in its specification about how large cells (and other components) should be.
Most issues seem to be that people have a set of required constraints that are incompatible with these encapsulation constraints also requiring a size of 0. The most workable answers seem to be to lower the priority of user defined constraints to 999 so that the framework's can overrule them.
However – what I'm interested in understanding is why is UITableView requiring a width of 0 for one of its views? Is this a bug? Or is it a results of incorrect use? Or does it make perfect sense?
Height constraints of 0 sometimes make sense, if cells are being expanded from nothing. Lowering priorities is a good way to handle this. But why would the cells be getting a width of 0?

UIView doesn't have the intrinsic size hence width and height constraints needed.
UIView-Encapsulated-Layout-Width and UIView-Encapsulated-Layout-Height are created by UICollectionView / UITableView initially. And later on sets the constraint constant based to the sizeForItem or heightForRowAtIndexPath delegate method. To ensure that UICollectionViewCell / UITableViewCell created in cellForItem / cellForRow method will be having the exact size.

Related

How to setup autolayout constraints properly for self-sizing cells

I've seen a lot of guides about self-sizing cells in iOS 7 and 8. Unfortunately, all of them shows very simple cases (I mean two UILabel's with same width and which placed like the first under the second and their constraints are very simple too). So I've a situation that seems to be not so much difficult but I can't resolve a problem.
I believe that it is very easy for the most of people and hope that somebody can help. The problem is that there is UITableViewCell with 3 child views inside.
Every view is UILabel. Labels placed in such order: two labels at the top of UITableViewCell with fixed size and one at the bottom with fixed width but with dynamic height. How should I setup my constraints properly to make my UITableViewCell be self-sizing?
The key to self-sizing is a vertical set of constraints that will determine the cell height. This isn't that complex, as you don't have two horizontal labels that vary in height.
Since headerLabel and dateLabel height don't vary, you only need to constrain the dynamicLabel to one of the two top labels.
In this example, we'll arbitrarily pick headerLabel to use in the vertical constraints. The spacing between the labels wasn't specified, so I'll assume it's 10. Adjust as necessary.
For your horizontal constraints, set leading and trailing space to the superview.
Your vertical constraints would simply look like "V:|-10-[headerLabel]-10-[dynamicLabel]-10-|" (and should
dynamicLabel will grow as tall as it needs, provided you set its numberOfLines to 0, and its height will end up determining the height of the cell.
Assuming the constraints are setup properly, and the storyboard cell height exactly matches the vertical height set by the constraints, you shouldn't see any storyboard warnings or errors, and should be good to go.
8.4 does address a number of issues, so you shouldn't require any specific (layoutSubViews/preferredMaxLayoutWidth/reloadData) code to work around earlier 8.x problems.
As an aside, a general tip is to pin your constraints to the superview margin, instead of the superView. This means your leading, trailing, top, and bottom constraints could be 2, instead of 10, since the margin is generally 8. This lets your white space adapt to different devices, which is a really nice touch.

Automatically set height of custom UIView based on its contents?

I’ve taken a lot of time to read other questions before asking this one, and haven’t managed to solve the issue yet – hopefully someone can help.
I have a custom alert view, a UIView subclass. I’m trying to get it into a state where its width is fixed, and its height grows dynamically based on the height of its two labels (title and message), and a dynamic number of action buttons it can be set up with.
I’ve used AutoLayout to set up the controls, which is working fine, but for now I’m still manually setting the frame of the view itself in its initialiser.
What I need to do is have the view’s height be calculated by the height of my two labels, and n buttons, plus the spacing between them.
I’ve tried providing an intrinsicContentSize for my view, but that method is never called, and it doesn’t even ask for it, so I’m stumped as to how to proceed.
To summarise: I probably need iOS9’s UIStackView, but I don’t have that luxury, so I need to bake something similar into iOS 7 / 8. I’ve looked at OAStackView but I’d rather not use an external dependency.
Just a quick thought: Have you tried to create the view in Interface Builder? Give it a fixed width with Priority: 1000. Add no Height constraint but center the view vertically in its superview.
Then set the View's vertical content hugging priority and vertical content compression resistance priority to 1000.
This should cause the view to calculate its own height based on its subviews. You only need to make sure, that the subviews are bound to the superview in a way that defines the height without any ambiguity.

UICollectionViewCell inside UITableView Cell and Auto Layout

I have anUICollectionView inside aUITableViewCell and I have some issues regarding to Auto layout.
That's the hierarchy of my views.
UITableViewCell
|
-------ContentView
|
-------MyView
|
|-----UICollectionViewCell
Until here, all views are pinned up in his superviews., e.g: trailing space=0, leading space=0, top space=0, bottom space 0.
The height of myUICollectionViewCell is dynamic, based on the number of itens, which I draw usingUICollectionViewLayout. So it has a height constraint which is >= 100.
After the Items are in place, I call one delegate to update that height constraint, so myUITableView is able to calculate the right height for theUITableViewCell.
Even though this are working fine, sometimes I get the auto layout error above.
How can I avoid this?
The cell's contentView has a fixed height (44). That's causing the occasional conflict between the storyboard, and Auto Layout's derived height.
Self-sizing is the best way to go. What you want to do is to get your "collection view" to determine its intrinsic size, so Auto Layout can automatically handle the variable cell height for you.
See the detailed walkthrough by smileyborg in his answer to Using Auto Layout in UITableView for dynamic cell layouts & variable row heights.
He uses labels but the principle is the same. The cell asks its contentView to lay itself out. The contentView asks the label to lay itself out. The label determines its height. Auto Layout determines the contentView's height, based on the label's constraints, and the cell determines its height, based on the contentView's height. The point is that the label doesn't have a height constraint, and your "collection View" would no longer need one either.
Once you adopt self-sizing, it eliminates a lot of code (and size constraints), as containers manage their size, and constraints simply handle spacing.

Please explain the following auto layout behavior to me

I'm currently trying to figure out what I am doing wrong with the following constraint-based UITableViewCell layout (iOS 8).
My cell is laid out as shown in this image:
There is an image view on the left, a label on the right, and both should be touching the cell margins everywhere. The image has a fixed size (64x64), the label's height will always be smaller than that. I want the image's height to cause the cell to expand the height to the correct value (image height + 2 * margin).
The problem is this: I have three constraints for the vertical size, V[Image(64)], Reset.bottom == UITableViewCellContentView.bottomMargin and Reset.top == UITableViewCellContentView.topMargin (all defined via the storyboard). When I display the cell, I get an unsatisfiable constraints error. The UIView-Encapsulated-Layout-Height constraint interferes with my constraints, and auto layout breaks my image view height constraint. Everything looks as it should, but I don't like errors at runtime.
If I give my height constraint the priority 999, everything looks fine, no errors.
So my understanding is, that my height constraint will be broken in both cases at runtime.
But when I delete the height constraint altogether, the image displays at its original height (the file has different resolution than what I display in the cell). Why is this, or what am I getting wrong here?
Edit/Update: I just noticed I was wrong about everything working. The initial display of my cell is fine, but when the cell changes (in my case I am moving another, simple single line label, cell below it) my cell changes its height to the default row height (44 pts), squashing the image in the process. This happens in both cases, when auto layout breaks my constraints or when I reduce the priority of height to 999. I'm really at a loss as to how to get these cells to do what I want.
You should try setting the estimatedRowHeight property in code, and also, depending on which version of iOS 6 you're using, set the rowHeight property to UITableViewAutomaticDimension,
self.tableView.estimatedRowHeight = 44;
self.tableView.rowHeight = UITableViewAutomaticDimension;
The default rowHeight for nib or storyboard table views, is supposed to be changed to UITableViewAutomaticDimension at some point; I don't know if it has yet in 6.0.1, so that last line may or may not be necessary.
Are you supporting older version of iOS? If that is the case, be sure to uncheck the Relative to margin option for the constraints that are complaining.

Resize UITextView inside a UITableViewCell with iOS Autolayout

My Goal
I'm creating a custom UITableViewCell (MessageCell), and I'd wish to have my UITextView resizing both in width and height whenever the cell changes its size, while keeping some basic constraint like margins to the edges.
Note : I also change my cell's height in the heightForRowAtIndexPath method depending on the content which will be placed into UITextView.
What I tried
Here are all the constraints currently applied & the cell :
I tried :
With a UILabel.
To fix a Vertical Space from the bottom, thinking it would change the height to fit all the constraints.
To override Height with an User Constraint Height >= 43 (my initial height), but the purple-automatic Height is re-created again whenever I do this.
To find a solution on SO first, but didn't find a case like (even if the UITextView's height's resize with autolayout seems to be a frequent issue).
Plenty of combinations of various & random constraints until my fingers bleds.
How it render now
So...
If someone has any clue or guideline to achieve my goal, I'd appreciate!
I might add, I'm totally new to Autolayout & constraints. My reference : Ray Wenderlich's awesomeness
You need to get rid of that height constraint that the text view has. Make sure you have constraints to something above and below the text view (usually the top and bottom of the cell), and then you should be able to delete that height constraint.

Resources