如何陷阱UIViewAlertForUnsatisfiableConstraints?

我看到一个错误出现在我的debugging器日志中:

Will attempt to recover by breaking constraint <NSLayoutConstraint:0x191f0920 H:[MPKnockoutButton:0x17a876b0]-(34)-[MPDetailSlider:0x17a8bc50](LTR)> 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. 

我该如何捕获这个电话? 它不出现在我的代码中的任何地方。

Screenshot1

这篇文章帮了我很多

我用build议的操作添加了UIViewAlertForUnsatisfiableConstraints符号断点:

Obj-C项目

 po [[UIWindow keyWindow] _autolayoutTrace] 

Swift项目

 expr -l objc++ -O -- [[UIWindow keyWindow] _autolayoutTrace] 

符号断点与自定义操作

有了这个提示,日志就变得更加细致了,而且我更容易识别哪个视图有约束被破坏。

 UIWindow:0x7f88a8e4a4a0 | UILayoutContainerView:0x7f88a8f23b70 | | UINavigationTransitionView:0x7f88a8ca1970 | | | UIViewControllerWrapperView:0x7f88a8f2aab0 | | | | •UIView:0x7f88a8ca2880 | | | | | *UIView:0x7f88a8ca2a10 | | | | | | *UIButton:0x7f88a8c98820'Archived' | | | | | | | UIButtonLabel:0x7f88a8cb0e30'Archived' | | | | | | *UIButton:0x7f88a8ca22d0'Download' | | | | | | | UIButtonLabel:0x7f88a8cb04e0'Download' | | | | | | *UIButton:0x7f88a8ca1580'Deleted' | | | | | | | UIButtonLabel:0x7f88a8caf100'Deleted' | | | | | *UIView:0x7f88a8ca33e0 | | | | | *_UILayoutGuide:0x7f88a8ca35b0 | | | | | *_UILayoutGuide:0x7f88a8ca4090 | | | | | _UIPageViewControllerContentView:0x7f88a8f1a390 | | | | | | _UIQueuingScrollView:0x7f88aa031c00 | | | | | | | UIView:0x7f88a8f38070 | | | | | | | UIView:0x7f88a8f381e0 | | | | | | | | •UIView:0x7f88a8f39fa0, MISSING HOST CONSTRAINTS | | | | | | | | | *UIButton:0x7f88a8cb9bf0'Retrieve data'- AMBIGUOUS LAYOUT for UIButton:0x7f88a8cb9bf0'Retrieve data'.minX{id: 170}, UIButton:0x7f88a8cb9bf0'Retrieve data'.minY{id: 171} | | | | | | | | | *UIImageView:0x7f88a8f3ad80- AMBIGUOUS LAYOUT for UIImageView:0x7f88a8f3ad80.minX{id: 172}, UIImageView:0x7f88a8f3ad80.minY{id: 173} | | | | | | | | | *App.RecordInfoView:0x7f88a8cbe530- AMBIGUOUS LAYOUT for App.RecordInfoView:0x7f88a8cbe530.minX{id: 174}, App.RecordInfoView:0x7f88a8cbe530.minY{id: 175}, App.RecordInfoView:0x7f88a8cbe530.Width{id: 176}, App.RecordInfoView:0x7f88a8cbe530.Height{id: 177} | | | | | | | | | | +UIView:0x7f88a8cc1d30- AMBIGUOUS LAYOUT for UIView:0x7f88a8cc1d30.minX{id: 178}, UIView:0x7f88a8cc1d30.minY{id: 179}, UIView:0x7f88a8cc1d30.Width{id: 180}, UIView:0x7f88a8cc1d30.Height{id: 181} | | | | | | | | | | | *UIView:0x7f88a8cc1ec0- AMBIGUOUS LAYOUT for UIView:0x7f88a8cc1ec0.minX{id: 153}, UIView:0x7f88a8cc1ec0.minY{id: 151}, UIView:0x7f88a8cc1ec0.Width{id: 154}, UIView:0x7f88a8cc1ec0.Height{id: 165} | | | | | | | | | | | | *UIView:0x7f88a8e68e10- AMBIGUOUS LAYOUT for UIView:0x7f88a8e68e10.minX{id: 155}, UIView:0x7f88a8e68e10.minY{id: 150}, UIView:0x7f88a8e68e10.Width{id: 156} | | | | | | | | | | | | *UIImageView:0x7f88a8e65de0- AMBIGUOUS LAYOUT for UIImageView:0x7f88a8e65de0.minX{id: 159}, UIImageView:0x7f88a8e65de0.minY{id: 182} | | | | | | | | | | | | *UILabel:0x7f88a8e69080'8-6-2015'- AMBIGUOUS LAYOUT for UILabel:0x7f88a8e69080'8-6-2015'.minX{id: 183}, UILabel:0x7f88a8e69080'8-6-2015'.minY{id: 184}, UILabel:0x7f88a8e69080'8-6-2015'.Width{id: 185} | | | | | | | | | | | | *UILabel:0x7f88a8cc0690'16:34'- AMBIGUOUS LAYOUT for UILabel:0x7f88a8cc0690'16:34'.minX{id: 186}, UILabel:0x7f88a8cc0690'16:34'.minY{id: 187}, UILabel:0x7f88a8cc0690'16:34'.Width{id: 188}, UILabel:0x7f88a8cc0690'16:34'.Height{id: 189} | | | | | | | | | | | | *UIView:0x7f88a8cc2050- AMBIGUOUS LAYOUT for UIView:0x7f88a8cc2050.minX{id: 161}, UIView:0x7f88a8cc2050.minY{id: 166}, UIView:0x7f88a8cc2050.Width{id: 163} | | | | | | | | | | | | *UIImageView:0x7f88a8e69d90- AMBIGUOUS LAYOUT for UIImageView:0x7f88a8e69d90.minX{id: 190}, UIImageView:0x7f88a8e69d90.minY{id: 191}, UIImageView:0x7f88a8e69d90.Width{id: 192}, UIImageView:0x7f88a8e69d90.Height{id: 193} | | | | | | | | | | | *UIView:0x7f88a8f3cc00 | | | | | | | | | | | | *UIView:0x7f88a8e618d0 | | | | | | | | | | | | *UIImageView:0x7f88a8e5ba10 | | | | | | | | | | | | *UIView:0x7f88a8f3cd70 | | | | | | | | | | | | *UIImageView:0x7f88a8e58e10 | | | | | | | | | | | | *UIImageView:0x7f88a8e5e7a0 | | | | | | | | | | | | *UIView:0x7f88a8f3cee0 | | | | | | | | | | | *UIView:0x7f88a8f3dc70 | | | | | | | | | | | | *UIView:0x7f88a8e64dd0 | | | | | | | | | | | | *UILabel:0x7f88a8e65290'Average flow rate' | | | | | | | | | | | | *UILabel:0x7f88a8e712d0'177.0 ml/s' | | | | | | | | | | | | *UILabel:0x7f88a8c97150'1299.4' | | | | | | | | | | | | *UIView:0x7f88a8f3dde0 | | | | | | | | | | | | *UILabel:0x7f88a8f3df50'Maximum flow rate' | | | | | | | | | | | | *UILabel:0x7f88a8cbfdb0'371.6 ml/s' | | | | | | | | | | | | *UILabel:0x7f88a8cc0230'873.5' | | | | | | | | | | | | *UIView:0x7f88a8f3e2a0 | | | | | | | | | | | | *UILabel:0x7f88a8f3e410'Total volume' | | | | | | | | | | | | *UILabel:0x7f88a8cc0f20'371.6 ml' | | | | | | | | | | | | *UIView:0x7f88a8f3e870 | | | | | | | | | | | | *UILabel:0x7f88a8f3ea00'Time do max. flow' | | | | | | | | | | | | *UILabel:0x7f88a8cc0ac0'3.6 s' | | | | | | | | | | | | *UIView:0x7f88a8f3ee10 | | | | | | | | | | | | *UILabel:0x7f88a8f3efa0'Flow time' | | | | | | | | | | | | *UILabel:0x7f88a8cbf980'2.1 s' | | | | | | | | | | | | *UIView:0x7f88a8f3f3e0 | | | | | | | | | | | | *UILabel:0x7f88a8f3f570'Voiding time' | | | | | | | | | | | | *UILabel:0x7f88a8cc17e0'3.5 s' | | | | | | | | | | | | *UIView:0x7f88a8f3f9a0 | | | | | | | | | | | | *UILabel:0x7f88a8f3fb30'Voiding delay' | | | | | | | | | | | | *UILabel:0x7f88a8cc1380'1.0 s' | | | | | | | | | | | | *UIView:0x7f88a8e65000 | | | | | | | | | | | | *UIButton:0x7f88a8e52f20'Show' | | | | | | | | | | | | *UIImageView:0x7f88a8e6e1d0 | | | | | | | | | | | | *UIButton:0x7f88a8e52c90'Send' | | | | | | | | | | | | *UIImageView:0x7f88a8e61bb0 | | | | | | | | | | | | *UIButton:0x7f88a8e528e0'Delete' | | | | | | | | | | | | *UIImageView:0x7f88a8e6b3f0 | | | | | | | | | | | | *UIView:0x7f88a8f3ff60 | | | | | | | | | *UIActivityIndicatorView:0x7f88a8cba080 | | | | | | | | | | UIImageView:0x7f88a8cba700 | | | | | | | | | *_UILayoutGuide:0x7f88a8cc3150 | | | | | | | | | *_UILayoutGuide:0x7f88a8cc3b10 | | | | | | | UIView:0x7f88a8f339c0 | | UINavigationBar:0x7f88a8c96810 | | | _UINavigationBarBackground:0x7f88a8e45c00 | | | | UIImageView:0x7f88a8e46410 | | | UINavigationItemView:0x7f88a8c97520'App' | | | | UILabel:0x7f88a8c97cc0'App' | | | UINavigationButton:0x7f88a8e3e850 | | | | UIImageView:0x7f88a8e445b0 | | | _UINavigationBarBackIndicatorView:0x7f88a8f2b530 Legend: * - is laid out with auto layout + - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES • - layout engine host 

然后我暂停执行 暂停 我用命令改变了问题视图的背景色

OBJ-C

 expr ((UIView *)0x7f88a8cc2050).backgroundColor = [UIColor redColor] 

Swift 3.0

 expr -l Swift -- import UIKit expr -l Swift -- unsafeBitCast(0x7f88a8cc2050, to: UIView.self).backgroundColor = UIColor.red 

…结果这真棒!

暗示的看法

简直太神奇了! 希望能帮助到你。

你会想添加一个Symbolic Breakpoint 。 苹果提供了一个很好的指导如何做到这一点。

  1. 打开Breakpoint Navigator cmd+7
  2. 点击左下方的Addbutton
  3. selectAdd Symbolic Breakpoint...
  4. 它只要inputUIViewAlertForUnsatisfiableConstraints

您也可以像处理其他任何断点一样处理它,打开和closures它,添加操作或logging消息。

遵循斯蒂芬的build议,并试图debugging代码和哇! 有效。 答案在于debugging消息本身。

Will attempt to recover by breaking constraint NSLayoutConstraint:0x191f0920 H:[MPKnockoutButton:0x17a876b0]-(34)-[MPDetailSlider:0x17a8bc50](LTR)>

上面的行告诉你,运行时通过消除这个约束。 也许你不需要你的button上的水平间距(MPKnockoutButton)。 一旦你清除这个约束,它不会在运行时抱怨,你会得到所需的行为。

每当我试图去除系统必须破坏的约束时,我的约束条件已经不足以满足IB(即在IB中显示“缺失约束”,这意味着它们是不完整的,将不会被使用)。 我实际上是通过设置要打破低优先级的约束来解决这个问题的(这是一个假设)可以让系统优雅地打破约束。 这可能不是最好的解决scheme,但它解决了我的问题,并由此产生的限制完美。