71

我已经完成并删除了每个用户约束,但在旋转设备后我仍然收到以下错误。我完全不知道为什么。有没有人有任何想法?

2013-01-14 21:30:31.363 myApp[35869:c07] 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) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x84543d0 h=--& v=--& V:[UIView:0xa330270(768)]>",
    "<NSLayoutConstraint:0xa338350 V:[UIView:0xa331260]-(-1)-|   (Names: '|':UIView:0xa330270 )>",
    "<NSLayoutConstraint:0xa338390 V:|-(841)-[UIView:0xa331260]   (Names: '|':UIView:0xa330270 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0xa338350 V:[UIView:0xa331260]-(-1)-|   (Names: '|':UIView:0xa330270 )>

Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
4

11 回答 11

112

让我们一一来看看。

"<NSAutoresizingMaskLayoutConstraint:0x84543d0 h=--& v=--& V:[UIView:0xa330270(768)]>"

这就是说视图 0xa330270 ( A ) 必须是 768 点高。

"<NSLayoutConstraint:0xa338350 V:[UIView:0xa331260]-(-1)-| (Names: '|':UIView:0xa330270 )>"

这就是说视图 0xa331260 ( B ) 的底部边缘与A底部的间隙必须为 -1 ,这是它的超级视图。

"<NSLayoutConstraint:0xa338390 V:|-(841)-[UIView:0xa331260] (Names: '|':UIView:0xa330270 )>"

这就是说B的上边缘必须与其父视图A的顶部相距 841 点。

这三件事不可能都是真的 - A不能是 768 点高,并且包含一个子视图,其顶部边缘从顶部插入 841 点,从底部插入 -1 点。您在哪里定义了这些约束?

你还没有说你想要实现什么布局,但看起来你可能在超级视图上有一个自动调整大小的掩码,当你旋转设备时它会阻止它的高度变化。据我所知,仅当您以编程方式添加视图时才会出现自动调整大小约束,因为情节提要或 xib 要么是全自动布局,要么不是。除非您正在执行诸如将自动布局视图(从笔尖加载?)添加到非自动布局笔尖的另一个视图之类的操作?

于 2013-01-14T21:56:15.127 回答
21

它值得了解基础知识,并了解 Apple/Xcode 试图通过日志告诉你什么

H = Horizontal constraint(for leading and Trailing)
V = Vertical constraint(top and bottom edge)
h = height
w = width

TopEdge    -> V:|-(points)-[VIEW:memoryAddress] 
BottomEdge -> V:[VIEW:memoryAddress]-(points)-|
Leading    -> H:|-(points)-[VIEW:memoryAddress] 
Trailing   -> H:[VIEW:memoryAddress] -(points)-|
height     -> h= --& v=--& V:[VIEW:memoryAddress((points)] 
width      -> VIEW:memoryAddress.width == points 
between    -> H:[VIEW 1]-(51)-[VIEW 2] 

一旦你理解了这一点,阅读你的具体错误就很容易了

于 2017-07-10T09:50:57.693 回答
19

感谢http://useYourLoaf.com提供完整的解决方案:

http://useyourloaf.com/blog/using-identifiers-to-debug-autolayout.html

我在 WWDC 2015 的 Auto Layout 会议中发现了一个快速提示,有助于调试约束问题

如果您使用过 Auto Layout,您将熟悉 Xcode 在出错时吐出的日志。为了创建一个示例,我修改了 Stack View 示例代码,并为每个图像添加了一个约束,为它们提供了 240 的固定宽度(我们将看到这不是一个好主意)。

在此处输入图像描述

这适用于 iPad 等常规宽度视图,但对于紧凑宽度视图(如 iPhone 纵向视图)来说太宽了。运行时的控制台日志读起来并不有趣。跳过样板文本,您将获得有问题的约束的列表:

"<NSLayoutConstraint:0x7fc1ab520360 H:[UIImageView:0x7fc1ab532650(240)]>",
"<NSLayoutConstraint:0x7fc1ab536ef0 H:[UIImageView:0x7fc1ab537380(240)]>",
"<NSLayoutConstraint:0x7fc1ab545cc0 UIView:0x7fc1ab53d870.trailingMargin == UIStackView:0x7fc1ab53dae0.trailing>",
"<NSLayoutConstraint:0x7fc1ab545d10 UIStackView:0x7fc1ab53dae0.leading == UIView:0x7fc1ab53d870.leadingMargin>",
"<NSLayoutConstraint:0x7fc1ab54e240 'UISV-alignment' UIStackView:0x7fc1ab53dc70.centerX == UIStackView:0x7fc1ab531a10.centerX>",
"<NSLayoutConstraint:0x7fc1ab5167c0 'UISV-canvas-connection' UIStackView:0x7fc1ab531a10.leading == UIImageView:0x7fc1ab532650.leading>",
"<NSLayoutConstraint:0x7fc1ab54ad80 'UISV-canvas-connection' H:[UIImageView:0x7fc1ab537380]-(0)-|   (Names: '|':UIStackView:0x7fc1ab531a10 )>",
"<NSLayoutConstraint:0x7fc1ab5397d0 'UISV-canvas-connection' UIStackView:0x7fc1ab53dae0.leading == _UILayoutSpacer:0x7fc1ab54c3c0'UISV-alignment-spanner'.leading>",
"<NSLayoutConstraint:0x7fc1ab54a4a0 'UISV-canvas-connection' UIStackView:0x7fc1ab53dae0.centerX == UIStackView:0x7fc1ab53dc70.centerX>",
"<NSLayoutConstraint:0x7fc1ab54b110 'UISV-spacing' H:[UIImageView:0x7fc1ab532650]-(16)-[UIImageView:0x7fc1ab537380]>",
"<NSLayoutConstraint:0x7fc1ab548210 'UISV-spanning-boundary' _UILayoutSpacer:0x7fc1ab54c3c0'UISV-alignment-spanner'.leading <= UIStackView:0x7fc1ab531a10.leading>",
"<NSLayoutConstraint:0x7fc1ab551690 'UIView-Encapsulated-Layout-Width' H:[UIView:0x7fc1ab53d870(375)]>"

然后,日志会告诉您它已决定打破上述哪些限制:

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7fc1ab536ef0 H:[UIImageView:0x7fc1ab537380(240)]>

日志输出使用自动布局视觉格式语言,但很难从系统创建的约束中挑选出我的约束。对于堆栈视图尤其如此,堆栈视图的设计旨在为您创建大部分约束。在这个简单的例子中,我知道我刚刚添加的固定宽度约束破坏了一些东西,但是从日志中很难看出这一点,而且视图越复杂,就越难。

将标识符添加到约束

NSLayoutConstraint如果您为每个约束添加一个标识符(自 iOS 7 以来就有一个标识符属性),那么日志会更容易理解。在 Interface Builder 中找到约束并在属性检查器中添加标识符(我使用 $ 作为前缀/后缀以使它们在日志中脱颖而出):

在此处输入图像描述

2015 年 8 月 18 日更新:正如评论中所指出的,标识符只能在从 Xcode 7 开始的 Interface Builder 中编辑。它在 Xcode 6.4 中不可见。

如果在代码中添加约束:

constraint.identifier = "$HeartImageFixedWidth$"

如果您使用的是使用约束数组的视觉格式语言,那就更棘手了。例如,考虑为心脏图像视图创建固定宽度约束的 Swift 代码片段:

let heartWidth = NSLayoutConstraint.constraintsWithVisualFormat("[heart(240)]", 
                 options:[], metrics:nil, views:viewsDictionary)

由于 heartWidth 是 [NSLayoutConstraint] 类型的数组,因此设置标识符需要做更多的工作:

for constraint in heartWidth {
  constraint.identifier = "$HeartImageFixedWidth$"
}
heartImage.addConstraints(heartWidth)

为我的约束设置标识后,现在可以更轻松地在日志文件中找到它们(参见前四行):

"<NSLayoutConstraint:0x7f92a305aeb0 '$ContainerStackViewLeading$' UIStackView:0x7f92a3053220.leading == UIView:0x7f92a3052fb0.leadingMargin + 32>",
"<NSLayoutConstraint:0x7f92a305b340 '$ContainerStackViewTrailing$' UIView:0x7f92a3052fb0.trailingMargin == UIStackView:0x7f92a3053220.trailing + 32>",
"<NSLayoutConstraint:0x7f92a301cf20 '$HeartImageFixedWidth$' H:[UIImageView:0x7f92a3047ef0(240)]>",
"<NSLayoutConstraint:0x7f92a3009be0 '$StarImageFixedWidth$' H:[UIImageView:0x7f92a304d190(240)]>",
"<NSLayoutConstraint:0x7f92a3060cc0 'UISV-alignment' UIStackView:0x7f92a30533b0.centerX == UIStackView:0x7f92a30472b0.centerX>",
"<NSLayoutConstraint:0x7f92a301c590 'UISV-canvas-connection' UIStackView:0x7f92a30472b0.leading == UIImageView:0x7f92a3047ef0.leading>",
"<NSLayoutConstraint:0x7f92a305f680 'UISV-canvas-connection' H:[UIImageView:0x7f92a304d190]-(0)-|   (Names: '|':UIStackView:0x7f92a30472b0 )>",
"<NSLayoutConstraint:0x7f92a3064190 'UISV-canvas-connection' UIStackView:0x7f92a3053220.leading == _UILayoutSpacer:0x7f92a30608a0'UISV-alignment-spanner'.leading>",
"<NSLayoutConstraint:0x7f92a30415d0 'UISV-canvas-connection' UIStackView:0x7f92a3053220.centerX == UIStackView:0x7f92a30533b0.centerX>",
"<NSLayoutConstraint:0x7f92a305fa10 'UISV-spacing' H:[UIImageView:0x7f92a3047ef0]-(16)-[UIImageView:0x7f92a304d190]>",
"<NSLayoutConstraint:0x7f92a30508c0 'UISV-spanning-boundary' _UILayoutSpacer:0x7f92a30608a0'UISV-alignment-spanner'.leading <= UIStackView:0x7f92a30472b0.leading>",
"<NSLayoutConstraint:0x7f92a3063240 'UIView-Encapsulated-Layout-Width' H:[UIView:0x7f92a3052fb0(375)]>"

它也更清楚系统选择打破哪些约束:

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7f92a3009be0 '$StarImageFixedWidth$' H:[UIImageView:0x7f92a304d190(240)]>

将标识符添加到约束并非不费吹灰之力,但它可以在您下次必须对复杂布局的调试日志进行排序时得到回报。

延伸阅读

于 2015-10-11T17:05:39.457 回答
9

我想这不是一个常见的错误,但我以一种外行的方式解决了它。我收到了像上面这样的神秘信息。为了理解它,我创建了虚拟视图类并将其附加到我的故事板中的视图中。例如,如果我有一个 UIView,我创建了一个名为 AddressView 的类并将它附加到故事板中的这个视图。它有点耗时,但它对我有用。在那之后,我得到了类名,而不是对象 ID,这帮助我将很容易导致问题的视图归零。我的错误信息现在阅读,

2013-07-02 04:16:20.434 Myproject [2908:c07] 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:0x9edeae0 V:|-(0)-[AddressView:0x143ee020]   (Names: '|':MainView:0x129eb6a0 )>",
    "<NSAutoresizingMaskLayoutConstraint:0x11e998c0 h=--& v=--& V:[MainView:0x129eb6a0(704)]>",
    "<NSLayoutConstraint:0x156720b0 V:[AddressView:0x143ee020]-(896)-|   (Names: '|':MainView:0x129eb6a0 )>"
)

在这里您可以看到,我的视图 MainView 和 Address 视图的名称导致了问题。

为了解决它,我只是移动了我的子视图(在本例中为地址视图)并将其重新定位。我认为问题开始于我在 Xcode 4.5 中使用新的 Automatic Layour 和旧技能或手动定位视图。

无论如何,不​​确定这是否比勤奋更幸运,但这可能是一种不同的调试方式。也许这对某人有帮助!

于 2013-07-02T02:30:40.447 回答
5

YourConstraintView.translatesAutoresizingMaskIntoConstraints = NO;

为我做了。

于 2016-04-12T07:34:48.333 回答
4

我已经解决了这个问题,即从 xib 文件中删除所有 translatesAutoresizingMaskIntoConstraints 属性(将 xib 作为源代码打开)。

于 2014-05-27T04:28:02.743 回答
3

一注。如果您使用个人热点连接进行测试,您会在日志中收到此错误,并且热点状态栏位于顶部。它摆脱了约束。

希望这对某人有所帮助..让我发疯了。

于 2016-01-08T23:36:17.487 回答
0

对我来说,这个错误在我给出时被吐出tableView.estimatedRowHeight = UITableViewAutomaticDimension

这应该是tableView.estimatedRowHeight = "Some hardcoded value"

于 2018-03-26T22:32:08.810 回答
0

我遇到了这个问题,花了我 2 天的时间来找出问题的根源....

如果您在代码中以编程方式打开情节提要,请确保您这样做:

UIStoryboard *story = [UIStoryboard storyboardWithName:@"MovieMaker" bundle:nil];
    UIViewController *vc = [story instantiateInitialViewController];
    //this causes layout to break [self presentViewController:vc animated:YES completion:nil];
    [self showViewController:vc sender:nil];

我正在使用注释行(使用presentViewController)并且方向错误发生了抛出不是我的约束的约束冲突......更改为showViewController所有约束冲突都消失了并且方向有效......(我没有真的知道为什么它适用于表演而不是在场......仍然认为它是......外星人......)

于 2018-04-30T22:28:03.177 回答
0

在调试控制台中生成的消息“无法同时满足约束”的问题在 XCode 9.4 中也遇到过。
在我在 iPad 模拟器上的特定实例中,该消息将生成:
1)仅当将焦点放在特定的 UITextField 上时。
2)即使删除了所有视图约束。
2)即使所有视图约束“重置为建议的约束”。

但是,当打开软件键盘进行显示时,不会生成该消息。因此,我应该在这个问题上花费多少时间,在我的实例中,只有在关闭软件键盘时才会生成。

于 2018-06-20T02:20:07.343 回答
0

当 uitableviewCell 中的上述日志时,此行解决了我的问题

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableView.automaticDimension > CellHeight.rowHeight44 ? UITableView.automaticDimension : CellHeight.rowHeight44
}
于 2021-01-15T10:26:21.683 回答