动画时无法同时满足约束

Posted

技术标签:

【中文标题】动画时无法同时满足约束【英文标题】:Unable to simultaneously satisfy constraints when animating 【发布时间】:2013-03-02 00:23:34 【问题描述】:

我使用 IB 设置了六个用户约束,如下所示:

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

我通过更改约束然后调用 layoutIfNeeded 来扩大和缩小视图。例如,为了增加视图,我会这样做:

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

然后调用

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

这种技术会扩大和缩小我的视野,看起来不错,但我收到了一个相当混乱的警告:

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)]>

现在所有这些约束都由 IB 生成。我已经双重^(三重!)检查了这个。我用笔和纸把这些限制放在一起,得到了这个:

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)-]

我不明白为什么不能满足这些限制。他们看起来很好。我不会更改它们,它们是由 IB 生成的。 IB产生的约束不是自动满足的吗?

或者,至少,有没有办法停止警告?它表现得非常完美,我不需要看到它打破了似乎没有做任何事情的约束。

【问题讨论】:

没有NSAutoResizingMaskLayoutConstraints,这不是重复的。 【参考方案1】:

这个约束:

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

似乎是系统分辨率的障碍。

你可以删除它吗?

【讨论】:

该约束由 IB 生成。当我删除它时,警告消失了,但我的视图在动画之后混乱了。嗯——也许我应该循环浏览所有视图。 啊哈!我找到了!我更改约束的顺序很重要!【参考方案2】:

所以,事实证明,我更改约束的顺序很重要。

为了扩大视野,我会

    增加宽度:H:|-(593)-[UIView(984)]-(20)-| 减少前导空格:H:|-(20)-[UIView(984)]-(20)-|

这不会产生任何警告。但是,如果我以相反的顺序执行此操作,我会收到警告:

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)]>

在缩小视图时,我复制了增加宽度的代码(以相同的顺序)并更改了值。这给了我在原始问题中发布的警告。当我切换收缩顺序时,警告消失了。


为什么会这样?我不知道。当我发现更多时,我会更新。

【讨论】:

很奇怪。你说的对。只是颠倒了我更新了一些约束的顺序,它消除了错误。【参考方案3】:

我收到了同样的信息,我终于明白了为什么会这样, 我的解决方案是:在动画的任何时刻都不要让任何对象翻转。

换句话说,约束应该在任何对象之外, 但有时在动画过程中会出现约束,这与我们的预期不同。

换句话说,不要因为约束动画而让上边距侵入下边距。

例如,

     top constraint: topA = initially 100

                    [Box A]

     bottom constraint: botA = initially 150

现在,如果你像下面这样设置动画,

      topA = 300
      botA = 25  

然后应该发生错误, 原因:线程在下边距下降之前侵入下边距。 所以, 你宁愿改变订单,

      botA = 25
      topA = 300

然后错误将消失,因为底部约束将保留质量的高度,而下一个顶部约束将缩小对象的高度而不侵入底部边距。

*要点: 即使在动画期间,也让对象的宽度和高度连续大于 0, 不受约束变化的干扰。

希望对你有所帮助。

【讨论】:

以上是关于动画时无法同时满足约束的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式应用自动布局约束时无法同时满足约束

存在 UIToolbarContentView 时无法同时满足约束

自动布局约束:无法同时满足约束

无法同时满足约束 - 在添加子视图时

尝试加载 xib 文件时无法同时满足约束

iOS - AutoLayout'无法同时满足约束'