UIStackView "Unable to simultaneously satisfy constraints" on "squished" hidden views - ios
When my UIStackView "rows" are squished, they throw AutoLayout warnings. However, they display fine and nothing else is wrong besides these sorts of loggings:
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)
(
So, I'm not sure how to fix this yet, but it doesn't seem to break anything besides just being annoying.
Does anyone know how to solve it? Interestingly, the layout constraints are tagged quite often with 'UISV-hiding', indicating that perhaps it should ignore the height minimums for subviews or something in this instance?
You get this issue because when setting a subview from within UIStackView to hidden, it will first constrain its height to zero in order to animate it out.
I was getting the following error:
2015-10-01 11:45:13.732 <redacted>[64455:6368084] 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:0x7f7f5be18c80 V:[UISegmentedControl:0x7f7f5bec4180]-(8)-| (Names: '|':UIView:0x7f7f5be69d30 )>",
"<NSLayoutConstraint:0x7f7f5be508d0 V:|-(8)-[UISegmentedControl:0x7f7f5bec4180] (Names: '|':UIView:0x7f7f5be69d30 )>",
"<NSLayoutConstraint:0x7f7f5bdfbda0 'UISV-hiding' V:[UIView:0x7f7f5be69d30(0)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7f7f5be18c80 V:[UISegmentedControl:0x7f7f5bec4180]-(8)-| (Names: '|':UIView:0x7f7f5be69d30 )>
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.
What I was trying to do, was to place a UIView within my UIStackView that contained a UISegmentedControl inset by 8pts on each edge.
When I set it to hidden, it would try to constrain the container view to a zero height but because i have a set of constraints from top to bottom, there was a conflict.
To resolve the issue, I changed my 8pt top an bottom constraints priority from 1000 to 999 so the UISV-hiding constraint can then take priority if needed.
I was having a similar problem that wasn't easy to resolve. In my case, I had a stack view embedded in a stack view. The internal UIStackView had two labels and a non-zero spacing specified.
When you call addArrangedSubview() it will automatically create constraints similar to the following:
V:|[innerStackView]| | = outerStackView
V:|[label1]-(2)-[label2]| | = innerStackView
Now when you try to hide the innerStackView, you get an ambiguous constraints warning.
To understand why, let's first see why this doesn't happen when innerStackView.spacing is equal to 0. When you call innerStackView.hidden = true, #liamnichols was correct... the outerStackView will magically intercept this call, and create a 0 height UISV-hiding constrain with priority 1000 (required). Presumably this is to allow elements in the stack view to be animated out of view in case your hiding code is called within a UIView.animationWithDuration() block. Unfortunately, there doesn't seem to be a way to prevent this constraint from being added. Nevertheless, you won't get an "Unable to simultaneously satisfy constraints" (USSC) warning, since the following happens:
label1's height is set to 0
the spacing between the two labels was already defined as 0
label2's height is set to 0
the innerStackView's height is set to 0
It's clear to see that those 4 constraints can be satisfied. The stack view simply smooshes everything into a 0-height pixel.
Now going back to the buggy example, if we set the spacing to 2, we now have these constraints:
label1's height is set to 0
the spacing between the two labels was automatically created by the stack view as 2 pixels high at 1000 priority.
label2's height is set to 0
the innerStackView's height is set to 0
The stack view cannot both be 0 pixels high and have its contents be 2 pixels high. The constraints cannot be satisfied.
Note: You can see this behavior with a simpler example. Simply add a UIView to a stack view as an arranged subview. Then set a height constraint on that UIView with 1000 priority. Now try calling hide on that.
Note: For whatever reason, this only happened when my stack view was a subview of a UICollectionViewCell or UITableViewCell. However, you can still reproduce this behavior outside of a cell by calling innerStackView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize) on the next run loop after hiding the inner stack view.
Note: Even if you try executing the code in a UIView.performWithoutAnimations, the stack view will still add a 0 height constraint which will cause the USSC warning.
There are at least 3 solutions to this problem:
Before hiding any element in a stack view, check if it's a stack view, and if so, change the spacing to 0. This is annoying because you need to reverse the process (and remember the original spacing) whenever you show the content again.
Instead of hiding elements in a stack view, call removeFromSuperview. This is even more annoying since when you reverse the process, you need to remember where to insert the removed item. You could optimize by only calling removeArrangedSubview and then hiding, but there is a lot of bookkeeping that still needs to be done.
Wrap nested stack views (which have non-zero spacing) in a UIView. Specify at least one constraint as non-required priority (999 or below). This is the best solution since you don't have to do any bookkeeping. In my example, I created top, leading, and trailing constraints at 1000 between the stack view and the wrapper view, then created a 999 constraint from the bottom of the stack view to the wrapper view. This way when the outer stack view creates a zero height constraint, the 999 constraint is broken and you don't see the USSC warning. (Note: This is similar to the solution to Should the contentView.translatesAutoResizingMaskToConstraints of a UICollectionViewCell subclass be set to false)
In summary, the reasons you get this behavior are:
Apple automatically creates 1000 priority constraints for you when you add managed subviews to a stack view.
Apple automatically creates a 0-height constraint for you when you hide a subview of a stack view.
Had Apple either (1) allowed you to specify the priority of constraints (especially of spacers), or (2) allowed you to opt-out of the automatic UISV-hiding constraint, this problem would be easily resolved.
Most of the time, this error can be resolved by lowering the constraints priority in order to eliminate conflicts.
When you set a view to hidden, the UIStackview will try to animate it away. If you want that effect, you'll need to set the right priority for the constraints so they don't conflict (as many has suggested above).
However if you don't care for the animation (perhaps you're hiding it in ViewDidLoad), then you can simple removeFromSuperview which will have the same effect but without any issues with constraints since those will be removed along with the view.
Based on #Senseful's answer, here is a UIStackView extension to wrap a stack view in a view and apply the constraints he or she recommends:
/// wraps in a `UIView` to prevent autolayout warnings when a stack view with spacing is placed inside another stack view whose height might be zero (usually due to `hidden` being `true`).
/// See http://stackoverflow.com/questions/32428210
func wrapped() -> UIView {
let wrapper = UIView()
translatesAutoresizingMaskIntoConstraints = false
wrapper.addSubview(self)
for attribute in [NSLayoutAttribute.Top, .Left, .Right, .Bottom] {
let constraint = NSLayoutConstraint(item: self,
attribute: attribute,
relatedBy: .Equal,
toItem: wrapper,
attribute: attribute,
multiplier: 1,
constant: 0)
if attribute == .Bottom { constraint.priority = 999 }
wrapper.addConstraint(constraint)
}
return wrapper
}
Instead of adding your stackView, use stackView.wrapped().
First, as others have suggested, make sure the constraints that you can control, i.e. not the constraints inherent to UIStackView are set to priority 999 so they can be overridden when the view is hidden.
If you are still experiencing the issue, then the problem is likely due to the spacing in the hidden StackViews. My solution was to add a UIView as a spacer and set UIStackView spacing to zero. Then set the View.height or View.width constraints (depending on a vertical or horizontal stack) to the spacing of the StackView.
Then adjust the content hugging and content compression resistance priorities of your newly added views. You might have to change the distribution of the parent StackView as well.
All of the above can be done in Interface Builder. You might additionally have to hide/unhide some of the newly added views programmatically so you do not have unwanted spacing.
I recently wrestled with auto layout errors when hiding a UIStackView. Rather than do a bunch of book keeping and wrapping stacks in UIViews, I opted to create an outlet for my parentStackView and outlets for the children I want to hide/unhide.
#IBOutlet weak var parentStackView: UIStackView!
#IBOutlet var stackViewNumber1: UIStackView!
#IBOutlet var stackViewNumber2: UIStackView!
In storyboard, here's what my parentStack looks like:
It has 4 children and each of the children have a bunch of stack views inside of them. When you hide a stack view, if it's got UI elements that are stack views as well, you'll see a stream of auto layout errors. Rather than hide, I opted to remove them.
In my example, parentStackViews contains an array of the 4 elements: Top Stack View, StackViewNumber1, Stack View Number 2, and Stop Button. Their indices in arrangedSubviews are 0, 1, 2, and 3, respectively. When I want to hide one, I simply remove it from parentStackView's arrangedSubviews array. Since it's not weak, it lingers in memory and you can just put it back at your desired index later. I'm not reinitializing it, so it just hangs out until it's needed, but doesn't bloat memory.
So basically, you can...
1) Drag IBOutlets for your parent stack and the children you want to hide/unhide to the storyboard.
2) When you want to hide them, remove the stack you want to hide from parentStackView's arrangedSubviews array.
3) Call self.view.layoutIfNeeded() with UIView.animateWithDuration.
Note the last two stackViews are not weak. You need to keep them around for when you unhide them.
Let's say I want to hide stackViewNumber2:
parentStackView.removeArrangedSubview(stackViewNumber2)
stackViewNumber2.removeFromSuperview()
Then animate it:
UIView.animate(withDuration: 0.25,
delay: 0,
usingSpringWithDamping: 2.0,
initialSpringVelocity: 10.0,
options: [.curveEaseOut],
animations: {
self.view.layoutIfNeeded()
},
completion: nil)
If you want to "unhide" a stackViewNumber2 later, you can just insert it in the desired parentStackView arrangedSubViews index and animate the update.
parentStackView.removeArrangedSubview(stackViewNumber1)
stackViewNumber1.removeFromSuperview()
parentStackView.insertArrangedSubview(stackViewNumber2, at: 1)
// Then animate it
UIView.animate(withDuration: 0.25,
delay: 0,
usingSpringWithDamping: 2.0,
initialSpringVelocity: 10.0,
options: [.curveEaseOut],
animations: {
self.view.layoutIfNeeded()
},
completion: nil)
I found that to be a lot easier than doing bookkeeping on constraints, fiddling with priorities, etc.
If you have something you want hidden by default, you could just lay it out on storyboard and remove it in viewDidLoad and update without the animation using view.layoutIfNeeded().
I experienced the same errors with embedded Stack Views, though everything worked fine at runtime.
I solved the constraint errors by hiding all the sub-stack views first (setting isHidden = true) before hiding the parent stack view.
Doing this did not have all the complexity of removing sub arranged views, maintaining an index for when needing to add them back.
Hope this helps.
Senseful have provided an excellent answer to the root of the problem above so I'll go straight to the solution.
All you need to do is set all stackView constraints priority lower than 1000 (999 will do the work). For example if the stackView is constrained left, right, top, and bottom to its superview then all 4 constraints should have the priority lower than 1000.
You might have created a constraint while working with a certain size class (ex: wCompact hRegular) and then you created a duplicate when you switched to another size class (ex: wAny hAny). check the constraints of the UI objects in different size classes and see if there are anomalies with the constraints. you should see the red lines indicating colliding constraints. I can't put a picture until I get 10 reputation points sorry :/
I wanted to hide whole UIStackView's at a time but I was getting the same errors as the OP, this fixed it for me:
for(UIView *currentView in self.arrangedSubviews){
for(NSLayoutConstraint *currentConstraint in currentView.constraints){
[currentConstraint setPriority:999];
}
}
I had a row of buttons with height constraint. This happens when one button is hidden. Setting the priority of that buttons height constraint to 999 have resolved the issue.
This error has nothing to do with UIStackView. It happens when you have conflict constrains with the same priorities. For example, if you have a constrain states that the width of your view is 100, and you have another constrain at the same time states that the view's width is 25% of its container. Obvious there are two conflicting constrains. The solution is to delete on of them.
NOP with [mySubView removeFromSuperview].
I hope it could help someone :)
Related
UISTackview constraint error in a UIScrollview in viewcontroller
I was trying to add a UISTackview in a scrollview. I believe the UIScrollview setup is right as the following screen has scrolled. Please note that it does not have any stackview, I have added a button with big top constraint so that I can see whether the scrollview works or not. Next, I added the stackview and just added the top, left, right constraint but not bottom constraint like the following image. However, since there is no bottom constraint, the scrollview does not work. When I added the bottom constraint, it shows the error like the following image because none of the textfields has height constraints. If I change the distribution to "Fill Equally". The textfields are taking too much blank spaces depending on the screen size. How can I use the stackview inside the scrollview. I want to use it as I want some of the views hidden based on conditions and claim the space. Any suggestion would be helpful. Thanks
Your second image is correct - but you need one more constraint. Add a constraint from the Bottom of the Stack View to the Bottom of View (its superview), but set it to >= 0 A couple of tips... rename your UI elements... it gets very confusing to refer to elements by default generic names (you have more than one View, for example). give your objects contrasting background colors during development... makes it much, much easier to see the frames.
Auto Layout of view hides subviews
I have a UIViewController embedded in a Navigation Controller. I am using autolayout. In interface builder this is how the VC looks. But when run in the simulator I get this: With this error. 2016-08-10 16:51:17.077 My App[11797:7752671] 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) ( "<_UILayoutSupportConstraint:0x7fad72f7d6b0 V:[_UILayoutGuide:0x7fad72e5d1d0(64)]>", "<_UILayoutSupportConstraint:0x7fad72ffa6a0 V:|-(0)-[_UILayoutGuide:0x7fad72e5d1d0] (Names: '|':UIView:0x7fad72fe1b40 )>", "<_UILayoutSupportConstraint:0x7fad72fe2460 V:[_UILayoutGuide:0x7fad72e64760(0)]>", "<_UILayoutSupportConstraint:0x7fad72fe1470 _UILayoutGuide:0x7fad72e64760.bottom == UIView:0x7fad72fe1b40.bottom>", "", "", "", "") 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 may also be helpful. I have rebuilt this view several times. I go up to Editor > Resolve Auto Layout Issues > "All Views" Reset to Suggested Constrains. Which generates this: I have even manually deleted all constrains and started over. But nothing works. I have nothing in the .m file that lays anything out or adjust sizes or locations. Nothing fancy is happening with this view. What am I doing wrong?
Editor > Resolve Auto Layout Issues > "All Views" Reset to Suggested Constrains almost never works correctly. So just avoid it. When adding constraints, you need to specify four things for every item: X location Y location Width Height There are creative ways to do this, so for you I would suggest you add these constraints to the Lookup Button: Horizontally in center Leading Space To Superview or Trailing Space to Superview (you do not need both) Height Top Space to Call Number Your x location and width are satisfied by Horizontally in Center and Leading or Trailing Space. These two constraints center the button and give you equal space on either side of the button. The button will be as wide as the view minus the space on both sides. Setting the height obviously satisfies the height of the button and Top Space satisfies the y position of your button. Therefore you have easily satisfied x location, y location, width and height of the button, and you are done.
plz set your constraints as following image
You need to start over and think about constraints you are making. Think about what information is known, what sizes should not change. Tell this information to Auto Layout. Your button is not appearing because Auto Layout does not known how to position it, it missing following numbers. Delete all constraints and start over with the following. Not you can change this numbers. Txt Search.top = Top Layout Guide.bottom. This is yours, it is correct. Txt Search.height = 20.0 Txt Search.leading = 0 with margin Txt Search.trailing = 0 with margin Lookup.top = Txt.Search.bottom + standard margin Lookup.leading = 0 with margin Lookup.trailing = 0 with margin Lookup.height = 20.0
Reset to suggested constraints never solves your problem, it only hides the warning. You have to set the constraints that suits for your requirement. From your question, when you choose the option, Reset to suggested constraints, the autolayout will give a bottom layout constraint for the LOOK UP button,and it had too much of bottom constraint(which happens when you rest to suggested constraint), hence it is pushed up in the runtime. You just need top and leading/ top and center horizontal constraint for your button corresponding to its above textfield along with height and width constraint. Remove the bototm constraint for your LOOK up button.
Xcode7 - equal heights multiplier constraint causing conflicting constraints
I am attempting pretty much the same thing as the OP of this question in Xcode7. My end goal is to have a vertical StackView with two child views: one that occupies 70% of the parent's height, and one that occupies the remaining 30%. I followed the instructions in the post I linked. I selected the child view (which is a GMSMapView) and the parent StackView and checked the equal heights box in the Pin constraints menu. That worked just fine and dandy. However, when I edited that constraint from the GMSMapView's size inspector and changed the multiplier to .7, suddenly I get a conflicting constraints error! Here is a picture of the scene I am working on right now: And here is a picture of the error: Does anyone know how to resolve these conflicts? I tried turning off Autoresize Subviews but I am not sure that worked since I can't delete some of the constraints displayed in the error message.
The height of a UIStackView is based off of the size of its subviews (Unless your using UIStackViewDistributionFillEqually). The first two conflicting constraints evaluate to this Stack View.height = View.height Map View.height = 0.7 x Stack View.height But since the UIStackView bases its height on its subviews, there is essentially a third constraint. Stack View.height = Map View.height All of these constraints can not exist together since they conflict. There are two options I can think of. Remove the UIStackView. Since it only contains one view, you aren't getting any benefit from using it and it's only complicating things. If that's not an option, you will need to remove some constraints so that you aren't constraining the UIStackView to a specific height.
Changing NSLayoutConstraint constant in cellForRowAtIndexPath continually leads to "unable to satisfy constraints" error
I have numerous cells in my application like this. Some self sizing, others not. For example, let's say we have a custom UITableViewCell. 100 height. Inside it's content view, we drag 2 UIView's. UIViewTop and UIViewBottom. Each 50 in height. UIViewTop we place at the top of the content view, and give it Leading/Trailing/Top/Height constraints. UIViewBottom we place at the bottom of the content view, and give it Leading/Trailing/Bottom/Height constraints. We also give Vertical Spacing constraint between UIViewTop and UIViewBottom. Now, sometimes we want just UIViewTop to show, and other times we want UIViewTop AND UIViewBottom to show. So we drag out the UIViewBottomHeight Constraint as an IBOutlet NSLayoutConstraint. Then, in cellForRowAtIndexPath... we either set this IBOutlet constraint to 0 or to 50, depending on whether we want to show that portion or not. If we have self sizing cells we don't do anything. If we don't have self sizing cells, the cell's size is accurately determined in heightForRowAtIndexPath. I'm getting the warning under both circumstances. In the debugger, it will happening immediately after the following the code... `cell.constraintUIViewBottomHeight.constant = __` I want to be able to change the constraint constants, but not receive the Unable to simultaneously satisfy constraints warning in the console.
I'm guessing the priority for constraintUIViewBottomHeight constraint is Required/1000.. I'd give a shot by lowering the priority to 999 or something to get rid of the warning..
It sounds like the problem is arising because you have both a height constraint and a bottom to container constraint on the UIView at the bottom. If you change the height, the bottom to container constraint is off. You should be able to use just the height (or just the bottom to container) and get rid of the bottom to container constraint (or height constraint) altogether. Auto layout only needs enough constraints to determine the element's unique size and location.
Auto-layout: What creates constraints named UIView-Encapsulated-Layout-Width & Height?
My layout constraints are fine in Interface Builder but an exception occurs at runtime thanks to some part of the framework applying fixed height and width constraints that I really don't want. Why are they there, and how to turn them off? They're the last two constraints shown in the logged list: 2014-04-26 09:02:58.687 BBCNews[32058: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:0xbf478a0 UIView:0xbf4a3c0.height == 0.28125*UIView:0xbf4a3c0.width>", "<NSLayoutConstraint:0xbf47190 UIView:0xbf4a3c0.leading == BNMyNewsCell_landscape:0xbf48b10.leading>", "<NSLayoutConstraint:0xbf47160 UIView:0xbf4a3c0.trailing == BNMyNewsCell_landscape:0xbf48b10.trailing>", "<NSLayoutConstraint:0xbf47130 BNMyNewsCell_landscape:0xbf48b10.bottom == UIView:0xbf4a3c0.bottom>", "<NSLayoutConstraint:0xbf47100 UIView:0xbf4a3c0.top == BNMyNewsCell_landscape:0xbf48b10.top>", "<NSLayoutConstraint:0xd4c3c40 'UIView-Encapsulated-Layout-Width' H:[BNMyNewsCell_landscape:0xbf48b10(304)]>", "<NSLayoutConstraint:0xd4c38a0 'UIView-Encapsulated-Layout-Height' V:[BNMyNewsCell_landscape:0xbf48b10(290)]>" } Will attempt to recover by breaking constraint <NSLayoutConstraint:0xbf478a0 UIView:0xbf4a3c0.height == 0.28125*UIView:0xbf4a3c0.width>
Based on a ton of observation I believe (but cannot know for certain) that the constraints named UIView-Encapsulated-Layout-Width and UIView-Encapsulated-Layout-Height are created by UICollectionView and friends, and exist to enforce the size returned by the sizeForItemAtIndexPath delegate method. I guess it's there to ensure that the UICollectionViewCell set up by cellForItemAtIndexPath ends up the size that it was told it would be. Which answers my initial question here. A second question is why were the constraints unsatisfiable? The cell's intrinsic height should have been the same as UIView-Encapsulated-Layout-Height. Again, I don't know for certain, but I suspect it was a rounding error (i.e. intrinsic height came to 200.1 pixels, the UIView-Encapsulated-Layout-Height maybe rounded to 200. The fix I came up with was to just lower the priority of the relevant cell constraint to allow UIView-Encapsulated-Layout-Height to have the last word.
This may not answer your question, but it could help others like me who got here from search. I was getting a strange AutoLayout broken constraint error accompanied by a UIView-Encapsulated-Layout-Width constraint because I was adding a tableHeaderView to a table view that hadn't been sized with AutoLayout yet. So the system was trying to apply my header subviews' constraints inside a tableview with a frame of {0,0,0,0}. Since UITableView likes control over the width of its elements, its generated width constraint, UIView-Encapsulated-Layout-Width, was set to zero, causing all kinds of confusion with my header elements that were expecting 320+pt width. The takeaway: make sure you are adding/manipulating your supplementary/header/footer views after the tableview has been sized by AutoLayout.
I was facing the same weird constraint and had no idea why, until I remembered the darned translatesAutoresizingMaskIntoConstraints property. Setting this to false solved the problem. What happens in the background is that the auto resizing masks (the old layout engine for iOS) are converted to constraints. Very often you don't want these constraints and want your own ones. In such cases you should set this property to false and you'll be fine: view.translatesAutoresizingMaskIntoConstraints = false
Definitely seeing this on a UITableView's tableHeaderView. I was able to get this to work with a custom header view by explicitly setting the width equal to that of the tableView after setting the tableHeaderView, THEN resetting it after a layout pass has completed. Example code for iOS 9, which assumes you have a UITableView passed into your method as tableView and an item to configure it as item: //Create the header view self.contentDetailHeaderView = MyCustomHeaderView() //Turn on autolayout self.contentDetailHeaderView.translatesAutoresizingMaskIntoConstraints = false //Add the header to the table view tableView.tableHeaderView = self.contentDetailHeaderView //Pin the width let widthConstraint = NSLayoutConstraint(item: self.contentDetailHeaderView, attribute: .Width, relatedBy: .Equal, toItem: tableView, attribute: .Width, multiplier: 1, constant: 0) tableView.addConstraint(widthConstraint) //Do whatever configuration you need to - this is just a convenience method I wrote on my header view. self.contentDetailHeaderView.setupForItem(item) //Lay out the configured view self.contentDetailHeaderView.layoutIfNeeded() //Reset the table header view, because ¯\_(ツ)_/¯ tableView.tableHeaderView = self.contentDetailHeaderView Couple of notes, mostly for when I look this up again because I have the memory of a goldfish: You do not have to call this from viewDidLayoutSubviews - I was able to use this technique as long as the tableView has the appropriate width during setup. You do need to make sure your header view is set up to automatically resize itself. I did this by creating a .xib and then making sure all items were pinned so that as the view changed width, the height would then update. If you're trying to do this for viewForHeaderInSection, you're probably better off grabbing something offscreen which you can lay out a la this technique. I haven't had much luck with the self-sizing bits.
We've started seeing tons of layout conflicts in iOS 11 that include references to these constraints and they are in fact added via the translatesAutoresizingMaskIntoConstraints flag. It seems that in iOS 11 there's a lot more AutoLayout magic happening when a view is added to the hierarchy rather than just when the view is laid out (as it seemed to work in previous iOS versions). This is the case that we were running into: Create a view whose internal layout helps define the views size (e.g., the view has internal constraints that includes explicit padding, etc.) *** Add this view to the hierarchy. Set the translatesAutoresizingMaskIntoConstraints to false some time later, before the layout pass. The second step (***) will result in a conflict because the system will add zero size constraints to the view at the time the view is added to the hierarchy. We were setting translatesAutoresizingMaskIntoConstraints later as a result of using the PureLayout framework which automatically sets this flag correctly when you constrain the view... That said, in iOS 11 you need to remember to turn off translatesAutoresizingMaskIntoConstraints at construction time, before the view is added to the hierarchy. I suspect Apple thought that defaulting this flag to YES would be way more helpful than it is painful. Unfortunately, this has not been the case.
After banging my head for a while i found this link. In my case it was happening on the UITableViewHeaderFooterView when i was using insertRows or deleteRows from my UIVieController. 'estimatedSectionHeaderHeight' and 'estimatedRowHeight' where set, my constraints redone 3 times ... The error shown was: "<NSLayoutConstraint:0x280648140 H:|-(8)-[UIImageView:0x106e94860] (active, names: '|':DAT_Air_Vinyl.ExportsAlbumTableViewHeader:0x106e8fb50 )>", "<NSLayoutConstraint:0x280648230 H:[UIImageView:0x106e94860]-(8)-[DAT_Air_Vinyl.MainLabel:0x106ea5750'The Coral - The Invisible...'] (active)>", "<NSLayoutConstraint:0x280648410 H:[UIButton:0x106ea5a40]-(8)-| (active, names: '|':DAT_Air_Vinyl.ExportsAlbumTableViewHeader:0x106e8fb50 )>", "<NSLayoutConstraint:0x280648460 H:[DAT_Air_Vinyl.MainLabel:0x106ea5750'The Coral - The Invisible...']-(8)-[UIButton:0x106ea5a40] (active)>", "<NSLayoutConstraint:0x2806493b0 'UIView-Encapsulated-Layout-Width' DAT_Air_Vinyl.ExportsAlbumTableViewHeader:0x106e8fb50.width == 0 (active)>" As stated on the link: "When you do insertRows or deleteRows with certain animation types, UIKit will animate the row height from 0 to full height or back. At the 0-end of that animation, the layout equations are impossible to solve if entire vertical axis is set to priority=1000. But lower just one constraint to 999 – say that bottom space to superview margin – and all is fine; the content will just drop-down, outside the cell’s bounds.". The solution was to set to 999 (or lower to 1000) the leading priority of the UIImageView.
I got this error in all sorts of circumstances (not necessarily tied to UICollectionView and friends as suggested by the correct answer here).. So my way of dealing with it was simply clearing all the constraints then building them again (only this time i have no fear of my constraints colliding with these pre-created ones): so in code: UIView *parentView = [viewInQuestion superview]; [parentView clearConstraintsOfSubview:viewInQuestion]; where clearConstraintsOfSubview is a category method on UIView: - (void)clearConstraintsOfSubview:(UIView *)subview { for (NSLayoutConstraint *constraint in [self constraints]) { if ([[constraint firstItem] isEqual:subview] || [[constraint secondItem] isEqual:subview]) { [self removeConstraint:constraint]; } } }
I was facing a similar issue and solved it with the following. Environment: Swift 5.0, xcode 10.2.1, Setting views programmatically Warning message: Unable to simultaneously satisfy constraints... 'UIView-Encapsulated-Layout-Width' UIView:0x0000000000.width == 0 (active)>" ) Code with warning override func loadView() { view = UIView() /// Adds the subviews to the view and sets their properties and constraints setupViews() } Code that cleared warning override func loadView() { /// Needed to set the frame of the root view to the window frame. let window = UIWindow() view = UIView(frame: window.frame) /// Adds the subviews to the view and sets their properties and constraints setupViews() } Notes on the loadView() method: "If you use Interface Builder to create your views and initialize the view controller, you must not override this method. You can override this method in order to create your views manually. If you choose to do so, assign the root view of your view hierarchy to the view property. The views you create should be unique instances and should not be shared with any other view controller object. Your custom implementation of this method should not call super." - Apple documentation Notes on the root view: "If you prefer to create views programmatically ... you do so by overriding your view controller’s loadView method. Your implementation of this method should do the following: Create a root view object. The root view contains all other views associated with your view controller. You typically define the frame for this view to match the size of the app window, which itself should fill the screen. However, the frame is adjusted based on how your view controller is displayed. See “View Controller View Resizing.” You can use a generic UIView object, a custom view you define, or any other view that can scale to fill the screen. Create additional subviews and add them to the root view." - Old apple documentation?
UIView-Encapsulated-Layout-* are the constraints used by table, collection, and stacks to layout elements as you told them to do it. If you later set constraints that create a change in size you’ll get a conflict. An example of this use case is cells that download images with variable size. This happens because we are used to layoutIfNeeded() to refresh the layout, but once a collection goes through the rendering cycle the cell size is set with encapsulated constraints. You need to manually invalidate the index path you need to refresh, e.g. let context = UICollectionViewLayoutInvalidationContext() context.invalidateItems(at: [cellIndexPath]) collectionView.collectionViewLayout.invalidateLayout(with: context) this will recursively create more invalidations to shift the positions of other cells and make space. If you set, e.g. a different height constraint to change the size of the cell it will instantly crash and then recover after you invalidate and the cell is layout again. To avoid this crash you can lower the priority of the height constraint below .required, for instance UILayoutPriority(999).
In my case, I was inadvertently setting up my programmatic constraints twice. As soon as I removed the duplicate call, the conflicts went away.
I catch this problem when I use AL create tableviewHeader I init tableview like below let table = UITableView.init(frame: .zero, style: .grouped) // set table constraint ... then I create tableviewHeader with AutoLayout. "<NSLayoutConstraint:0x600003d7d130 'UIView-Encapsulated-Layout-Width' UIView:0x7fe92bc55260.width == 0 (active)>" symbolic breakpoint appear After I refer #Yerk 's the answer. I change the frame when I init tableView let rect = CGRect(x: 0, y: 0, width: SCREEN_WIDTH, height: 0) let table = UITableView.init(frame:rect , style: .grouped) The problem seems to be solved
Finally I found solution for CollectionView! If You using storyBoard, like I am, it will help you! Interface Builder / Storyboard Go to storyBoard -> chose your CollectionView ScreenShot CollectionView Go to Size Inspector Then set Estimate Size to None ScreenShot Estimate Size Thats All!
I was having a similar problem found from testing Split View on the iPad Pro, and DesignatedNerd's answer worked but I didn't need so much code. Here is what I used: [self.tableView.tableHeaderView setTranslatesAutoresizingMaskIntoConstraints:NO]; NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:self.myTableHeaderView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.tableView attribute:NSLayoutAttributeWidth multiplier:1 constant:0]; NSLayoutConstraint *yConstraint = [NSLayoutConstraint constraintWithItem:self.myTableHeaderView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.tableView attribute:NSLayoutAttributeTop multiplier:1 constant:0]; [self.tableView addConstraints:#[widthConstraint, yConstraint]]; Note the addition of the Y Constraint, which binds the top of the tableHeaderView to the top of the tableView.
I had the same issue when adding constraints to a Table view header. It seem to occur when adding constraints with set constants when the bounds of the header was (0,0,0,0). I managed to fix this by only adding the constraints in the layout subviews method when the bounds of the header was not (0,0,0,0) if self.bounds == CGRect.zero { return }
constraint UIView-Encapsulated-Layout-Height is created with value you set in tableView.estimatedSectionHeaderHeight