Unable to simultaneously satisfy constraints when

2019-07-14 07:15发布

问题:

I have six user constraints setup with IB that look like this:

H:|-(593)-[UIView(411)]-(20)-|
V:|-(20)-[UIView(288)]-(396)-|

I grow and shrink the view by changing the constraints and then calling layoutIfNeeded. For example, to grow the view I will do:

H:|-(20)-[UIView(984)]-(20)-|
V:|-(20)-[UIView(663)]-(20)-|

And then call

[UIView animateWithDuration:.5 animations:^{
    [self.view layoutIfNeeded];
}];

This technique grows and shrinks my view, and it looks nice, but I'm given a rather confusing 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:0x148d5af0 H:[UIView:0x148d4e50(411)]>",
    "<NSLayoutConstraint:0x148cc940 H:[UITableView:0xace7600(319)]>",
    "<NSLayoutConstraint:0x148ce040 H:|-(NSSpace(20))-[UITableView:0xacd4e00]   (Names: '|':UIView:0x148cddd0 )>",
    "<NSLayoutConstraint:0x148cdf00 H:[UITableView:0xace7600]-(NSSpace(20))-|   (Names: '|':UIView:0x148cddd0 )>",
    "<NSLayoutConstraint:0x148cdea0 H:[UITableView:0xacd4e00]-(NSSpace(8))-[UITableView:0xace7600]>",
    "<NSLayoutConstraint:0x148d4c10 UIView:0x148cddd0.trailing == UIView:0x148cdd40.trailing>",
    "<NSLayoutConstraint:0x148d4b90 H:|-(0)-[UIView:0x148cddd0]   (Names: '|':UIView:0x148cdd40 )>",
    "<NSLayoutConstraint:0x148d6020 H:|-(320)-[UIView:0x148cdd40]   (Names: '|':UIView:0x148cd330 )>",
    "<NSLayoutConstraint:0x148d5fa0 UIView:0x148cdd40.trailing == UIView:0x148cd330.trailing>",
    "<NSLayoutConstraint:0x148d5f60 H:[UIView:0x148d4e50]-(NSSpace(20))-|   (Names: '|':UIView:0x148cd330 )>",
    "<NSLayoutConstraint:0x148d5ee0 H:|-(20)-[UIView:0x148d4e50]   (Names: '|':UIView:0x148cd330 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x148cc940 H:[UITableView:0xace7600(319)]>

Now all of these constraints are generated by IB. I've double^(triple!) checked this. I've put these constraints together with a pen and paper and have gotten this:

UIView_A H:[-(20)-[UIView_E]-(20)-] and H:[-(320)-(UIView_B)
UIView_B H:[-(0)-[UIView_D]
UIView_C H:[UIView_C(411)]
UIView_D H:[-(20)-[UITableView_F]-[UITableView_G(319)]-(20)-]

I don't understand how these constraints can't be satisfied. They look fine. I don't change them and they're generated by IB. Aren't constraints generated by IB automatically satisfiable?

Or, at a minimum, is there a way to stop warnings? It behaves perfectly and I don't need to see that it's breaking a constraint that doesn't seem to do anything anyway.

回答1:

This constraint:

H:[UITableView:0xace7600(319)]>"

seems to be an impediment for the system resolution.

Can you remove it ?



回答2:

So, it turns out, the order at which I change constraints matters.

To grow the view, I will

  1. Increase the width: H:|-(593)-[UIView(984)]-(20)-|
  2. Decrease the leading space: H:|-(20)-[UIView(984)]-(20)-|

This produces no warnings. However, if I do this in the opposite order, I'll get a warning:

Unable to simultaneously satisfy constraints.
Probably at least one of the constraints ...

...Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x1567f650 H:[UITableView:0x119e6200(319)]>

When shrinking the view, I copied the code that increased the width (with the same order) and just changed the values. That gave me the warning I posted in my original question. When I switched the order for shrinking, the warnings disappeared.


Why is this the case? I don't know. I'll update as I discover more.



回答3:

I got same message, and I finally got it why it happens,
My solution is: Do not let any object FLIP OVER during at any moment of the animation.

In other words, contraints are should be OUTside of any object, but sometimes constraints are inside during animation, not like our expection.

In another words, do not let top margin invade bottom margin due to constraint animation.

For example,

     top constraint: topA = initially 100

                    [Box A]

     bottom constraint: botA = initially 150

now, if you set like below and animate,

      topA = 300
      botA = 25  

then error should occur, why: thread invades the bottom margin BEFORE bottom margin go down. So, You'd rather change the ORDER,

      botA = 25
      topA = 300

Then error will disappear because bottom constraint would preserve the height of the mass and next top constraint would shrink the object's height not invading the bottom margin.

*Point: Let the object have width and height greater than 0 CONTINUALLY even during animation, not interrupted by constraints change.

I hope I helped you.