What is a 'UIView-Encapsulated-Layout-Width' constraint?

IosUicollectionviewAutolayoutNslayoutconstraintUicollectionviewlayout

Ios Problem Overview


I keep getting 'Unable to simultaneously satisfy constraints' exceptions (Xcode 5, iOS 7, both device and simulator), where one of the constraints in the list is something like this:

"<NSLayoutConstraint:0x165b23d0 'UIView-Encapsulated-Layout-Width'
H:[StoryPlayerCell:0x165affc0(0)]>"

I did not set this constraint myself. It's also not an NSAutoresizingMaskLayoutConstraint. But where does it come from? And how can I get rid of it?

I have no idea. And I can't find anything about 'UIView-Encapsulated-Layout-Width' in the Apple's documentation. Even the Google search returns nothing at all.

Any suggestions?

PS: I'm using this cell in a UICollectionView with a custom subclass of UICollectionViewFlowLayout. Maybe the 'Encapsulated-Layout' part has something to do with this?

Ios Solutions


Solution 1 - Ios

A quick and nice fix, is to assign 999 priority value to the custom constraints with high priority. The encapsulated & auto-generated constraints should dominate with higher priority than your constraints.

https://stackoverflow.com/a/25795758/590010

Solution 2 - Ios

i played with the sample, i think these codes is causing the Autolayout exception.

CGFloat height = MAX(0, -y + maxY); line 79 in CSStickyHeaderFlowLayout.m.

if you use a static value for the height like 200, the exception won't happen anymore. i can't understand what exactly is UIView-Encapsulated-Layout, but seems like dynamically changing the UICollectionViewLayoutAttributes frame may cause that problem. in the sample project, it's the height, in PO's problem, i guess it's the width. Maybe i can dig a little bit more into it, if you think that would be helpful

Solution 3 - Ios

My situation

For me, I knew (logically) that my programmatic constraints should have worked. I was updating them after rotation of the device.

My quick-and-easy solution without changing constraints was to make sure that this was all done on the main thread. Why? I'm not too sure, but I assume that the rotation update must be in an asynchronous thread.

How I fixed it

From:

topTitleLeadingAnchorLandscape.isActive = true

To:

DispatchQueue.main.async {
    self.topTitleLeadingAnchorLandscape.isActive = true
}

Hope this saves someone lots of time in the future! 

Solution 4 - Ios

I found this with iOS 10 builds where I was using UITableViewCell subclasses as normal views not as table rows. The cell was constraining its contentView to zero width.

The workaround I used was to just add the contentView to the view hierarchy instead of the tableview cell. I also made sure to retain the tableView cell (as it was no longer being retained by the view hierarchy itself).

Solution 5 - Ios

I can shed some light on the answer to the question. In my OS X app, I found such a mysterious constraint on the cell view of an NSTableView, (that is, an object which I had previously returned in the NSTableViewDelegate method -tableView:viewForTableColumn:row). I had also sent a setWidth:0.0 message to this same table column. Changing the parameter in that setWidth: from 0.0 to something else was reflected in the constant value of the mysterious constraint.

Conclusion: Constraints which log themselves with 'UIView-Encapsulated-Layout-Width' or 'NSView-Encapsulated-Layout-Width' are caused by setting the width of a table column, or something similar.

Solution 6 - Ios

I was having this issue with an NSView based table cell that was being added to NSTableView. I set a fixed width on the NSView because it must be at least that size to properly accommodate the content. However it could be larger.

Changing the width constraint from NSLayoutRelationEqual to NSLayoutRelationGreaterThanOrEqual eliminated the warning.

Going from this:

[self addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:panelWidth]];

to this, fixed it:

[self addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:panelWidth]];

This isn't a 100% solution because when the NSTableView decides it needs to be smaller for reasons I am still not clear about, it will still throw the breaking constraint warning.

Solution 7 - Ios

I often get this issue as a result of requesting that a collection view (or one of its parents) be laid out before it is actually part of the app's view hierarchy. What basically happens is this: lacking a UIWindow to determine the size of the new view controller's view, the system assigns an arbitrary width of 50 points to the collection's cells. This is often too small to contain its subviews, leading to the clash of constraints.

For example, if I call layoutIfNeeded during viewDidLoad then the view controller's view is still floating around without a parent and does not know how big it is. Besides, it would be unnecessary to perform layout at this point since the layout will be invalidated and recalculated when it is added to the hierarchy anyway.

Now, one could get around this as some have suggested by making some constraints optional but with very high priorities. This can be a useful general strategy, but in this case it likely is not. For example, if the content of the cell is inset from the sides of the cell by a certain amount, it's only likely to work if the constraint between the content and the cell's contentView is not at the required priority. This will make the size of the cell ambiguous, and will throw a different warning.

Messing with constraint priorities without knowing exactly what you're doing can also lead to unforeseen issues, especially when two constraints in the same axis have the same priority and parent. A common issue with stack views is when its children all have the same priority in its primary axis so it can't tell which one to shrink or expand when it cannot be its preferred size.

The best solution in my opinion is to try and avoid laying out the view before it is added to its parent. Add a Constraint breakpoint and run the app. Note the method in which the app stops for the warning; it will probably be on a call to layoutIfNeeded. Now, replace that with the following:

if view.superview != nil {
    view.layoutIfNeeded()
}

This may be all that you need to do. If you still experience this problem then it may be that the collection view's cells are too small, either due to a simple size miscalculation, a problem in its layout object's code, or that the cell's constraints force it to be a specific size that is not the same as the one it is being given by the layout.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGoodsquirrelView Question on Stackoverflow
Solution 1 - IosDZenBotView Answer on Stackoverflow
Solution 2 - IosXu YinView Answer on Stackoverflow
Solution 3 - IosGeorgeView Answer on Stackoverflow
Solution 4 - IosJoseph LordView Answer on Stackoverflow
Solution 5 - IosJerry KrinockView Answer on Stackoverflow
Solution 6 - IosCliff RibaudoView Answer on Stackoverflow
Solution 7 - IosAshView Answer on Stackoverflow