【问题标题】:Aspect ratio NSLayoutConstraint in UITableViewCell is breaksUITableViewCell 中的纵横比 NSLayoutConstraint 中断
【发布时间】:2018-09-07 16:57:56
【问题描述】:

我正在尝试在UITableViewCell 中为UIImageView 设置适当的NSLayoutConstraints。所需的约束如下:

  • 16:9 纵横比
  • 0 领先
  • 0 个尾随
  • 11 顶
  • 11 底

UIImageView 是单元格内容视图的唯一子视图。我设置了tableView.rowHeight = UITableViewAutomaticDimensiontableView.estimatedRowHeight = 80

2018-03-28 15:52:30.454688-0400 TestApp[28844:694668] [LayoutConstraints] 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. 
(
    "<NSLayoutConstraint:0x604000486cc0 UIImageView:0x7f91cf670470.width == 1.77778*UIImageView:0x7f91cf670470.height   (active)>",
    "<NSLayoutConstraint:0x604000486e50 H:|-(0)-[UIImageView:0x7f91cf670470]   (active, names: '|':UITableViewCellContentView:0x7f91cf66f7e0 )>",
    "<NSLayoutConstraint:0x604000486ef0 H:[UIImageView:0x7f91cf670470]-(0)-|   (active, names: '|':UITableViewCellContentView:0x7f91cf66f7e0 )>",
    "<NSLayoutConstraint:0x604000486f40 V:|-(11)-[UIImageView:0x7f91cf670470]   (active, names: '|':UITableViewCellContentView:0x7f91cf66f7e0 )>",
    "<NSLayoutConstraint:0x604000486ea0 V:[UIImageView:0x7f91cf670470]-(11)-|   (active, names: '|':UITableViewCellContentView:0x7f91cf66f7e0 )>",
    "<NSLayoutConstraint:0x604000487530 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7f91cf66f7e0.height == 233   (active)>",
    "<NSLayoutConstraint:0x6040004874e0 'UIView-Encapsulated-Layout-Width' UITableViewCellContentView:0x7f91cf66f7e0.width == 375   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x604000486cc0 UIImageView:0x7f91cf670470.width == 1.77778*UIImageView:0x7f91cf670470.height   (active)>

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.

点击“添加缺少的约束”按钮不会添加任何新的约束。值 1.77778 是我的纵横比的正确十进制表示。我不确定为什么运行时需要打破这个约束。

我还尝试使用 Action -> Debugger Command expr -l objc++ -O -- [[UIWindow keyWindow] _autolayoutTrace]UIViewAlertForUnsatisfiableConstraints 创建一个符号断点,但我发现打印输出没有帮助,因为它正在打印整个视图层次结构。我不确定“UILayoutGuide 的模糊布局”与我的 UITableView 或单元格有什么关系...

•UIWindow:0x7f94bd466e60
|   UITransitionView:0x7f94bd64b860
|   |   •UIView:0x7f94bd468e70
|   |   |   *<UILayoutGuide: 0x6000007bdb20 - "UIViewSafeAreaLayoutGuide", layoutFrame = {{0, 44}, {375, 734}}, owningView = <UIView: 0x7f94bd468e70; frame = (0 0; 375 812); autoresize = W+H; layer = <CALayer: 0x600000822ec0>>>
|   |   |   *UILabel:0x7f94bd469050'Test App'
|   |   UILayoutContainerView:0x7f94bd610f50
|   |   |   UINavigationTransitionView:0x7f94bd488fa0
|   |   |   |   UIViewControllerWrapperView:0x7f94bd6129d0
|   |   |   |   |   •UIView:0x7f94bd61cea0
|   |   |   |   |   |   *<UILayoutGuide: 0x6040001b7840 - "UIViewSafeAreaLayoutGuide", layoutFrame = {{0, 0}, {375, 690}}, owningView = <UIView: 0x7f94bd61cea0; frame = (0 88; 375 724); autoresize = W+H; layer = <CALayer: 0x6040002370a0>>>
|   |   |   |   |   |   *UITableView:0x7f94be080800
|   |   |   |   |   |   |   FancySDK.ImageCell:0x7f94bf025600'5EC2187C-4839-47A3-83E9-C...'
|   |   |   |   |   |   |   |   •UITableViewCellContentView:0x7f94bd749410
|   |   |   |   |   |   |   |   |   *UIImageView:0x7f94bd749810
|   |   |   |   |   |   |   |   _UITableViewCellSeparatorView:0x7f94bd749a40
|   |   |   |   |   |   |   FancySDK.ArticleCell:0x7f94bd8d9600'18CCDA82-E137-496E-AB0C-5...'
|   |   |   |   |   |   |   |   •UITableViewCellContentView:0x7f94bd49a0a0
|   |   |   |   |   |   |   |   |   *UIView:0x7f94bd48cfa0
|   |   |   |   |   |   |   |   |   |   *UIImageView:0x7f94bd48d180
|   |   |   |   |   |   |   |   |   |   *ic_expand:0x7f94bd48d3b0
|   |   |   |   |   |   |   |   |   |   *UILabel:0x7f94bd49c210'Apple will unveil the nex...'
|   |   |   |   |   |   |   |   |   |   *UILabel:0x7f94bd4a20d0'Apple’s annual Worldwide ...'
|   |   |   |   |   |   |   |   |   |   *UILabel:0x7f94bd49ccd0'https://www.theverge.com/...'
|   |   |   |   |   |   |   |   _UITableViewCellSeparatorView:0x7f94bd4a3990
|   |   |   |   |   |   |   UIImageView:0x7f94bd62f410
|   |   |   |   |   |   |   UIImageView:0x7f94bd62fbf0
|   |   |   |   |   |   *UIView:0x7f94bd61ccc0
|   |   |   •Recommended for You:0x7f94bd611580
|   |   |   |   _UIBarBackground:0x7f94bd614750
|   |   |   |   |   UIImageView:0x7f94bd615000
|   |   |   |   _UINavigationBarLargeTitleView:0x7f94bd50ff60'Recommended for You'
|   |   |   |   |   UILabel:0x7f94bd4822f0
|   |   |   |   •_UINavigationBarContentView:0x7f94bd60ad60'Recommended for You'
|   |   |   |   |   *<UILayoutGuide: 0x6040001b7e60 - "BackButtonGuide(0x7f94bd60aa00)", layoutFrame = {{0, 0}, {16, 44}}, owningView = <_UINavigationBarContentView: 0x7f94bd60ad60; frame = (0 0; 375 44); layer = <CALayer: 0x604000235ee0>>>
|   |   |   |   |   *<UILayoutGuide: 0x6040001b7d80 - "LeadingBarGuide(0x7f94bd60aa00)", layoutFrame = {{16, 0}, {24, 44}}, owningView = <_UINavigationBarContentView: 0x7f94bd60ad60; frame = (0 0; 375 44); layer = <CALayer: 0x604000235ee0>>>
|   |   |   |   |   *<UILayoutGuide: 0x6040001b7ca0 - "TitleView(0x7f94bd60aa00)", layoutFrame = {{46, 0}, {321, 44}}, owningView = <_UINavigationBarContentView: 0x7f94bd60ad60; frame = (0 0; 375 44); layer = <CALayer: 0x604000235ee0>>>
|   |   |   |   |   *<UILayoutGuide: 0x6040001b7bc0 - "TrailingBarGuide(0x7f94bd60aa00)", layoutFrame = {{367, 0}, {0, 44}}, owningView = <_UINavigationBarContentView: 0x7f94bd60ad60; frame = (0 0; 375 44); layer = <CALayer: 0x604000235ee0>>>
|   |   |   |   |   *<UILayoutGuide: 0x6040001b7ae0 - "UIViewLayoutMarginsGuide", layoutFrame = {{16, 0}, {343, 44}}, owningView = <_UINavigationBarContentView: 0x7f94bd60ad60; frame = (0 0; 375 44); layer = <CALayer: 0x604000235ee0>>>
|   |   |   |   |   *_UIButtonBarStackView:0x7f94bd62d8d0
|   |   |   |   |   |   *<UILayoutGuide: 0x6040001b8020 - "UIButtonBar.flexibleSpaceEqualSizeLayoutGuide", layoutFrame = {{0, 0}, {8, 0}}, owningView = <_UIButtonBarStackView: 0x7f94bd62d8d0; frame = (16 0; 24 44); layer = <CALayer: 0x604000237f40>>>- AMBIGUOUS LAYOUT for UILayoutGuide:0x6040001b8020'UIButtonBar.flexibleSpaceEqualSizeLayoutGuide'.minX{id: 446}, UILayoutGuide:0x6040001b8020'UIButtonBar.flexibleSpaceEqualSizeLayoutGuide'.minY{id: 447}, UILayoutGuide:0x6040001b8020'UIButtonBar.flexibleSpaceEqualSizeLayoutGuide'.Width{id: 367}, UILayoutGuide:0x6040001b8020'UIButtonBar.flexibleSpaceEqualSizeLayoutGuide'.Height{id: 448}
|   |   |   |   |   |   *<UILayoutGuide: 0x6040001b81e0 - "UIButtonBar.minimumInterItemSpaceLayoutGuide", layoutFrame = {{0, 0}, {8, 0}}, owningView = <_UIButtonBarStackView: 0x7f94bd62d8d0; frame = (16 0; 24 44); layer = <CALayer: 0x604000237f40>>>- AMBIGUOUS LAYOUT for UILayoutGuide:0x6040001b81e0'UIButtonBar.minimumInterItemSpaceLayoutGuide'.minX{id: 449}, UILayoutGuide:0x6040001b81e0'UIButtonBar.minimumInterItemSpaceLayoutGuide'.minY{id: 450}, UILayoutGuide:0x6040001b81e0'UIButtonBar.minimumInterItemSpaceLayoutGuide'.Height{id: 451}
|   |   |   |   |   |   *<UILayoutGuide: 0x6040001b7a00 - "UIButtonBar.minimumInterGroupSpaceLayoutGuide", layoutFrame = {{0, 0}, {8, 0}}, owningView = <_UIButtonBarStackView: 0x7f94bd62d8d0; frame = (16 0; 24 44); layer = <CALayer: 0x604000237f40>>>- AMBIGUOUS LAYOUT for UILayoutGuide:0x6040001b7a00'UIButtonBar.minimumInterGroupSpaceLayoutGuide'.minX{id: 452}, UILayoutGuide:0x6040001b7a00'UIButtonBar.minimumInterGroupSpaceLayoutGuide'.minY{id: 453}, UILayoutGuide:0x6040001b7a00'UIButtonBar.minimumInterGroupSpaceLayoutGuide'.Height{id: 454}
|   |   |   |   |   |   *<UILayoutGuide: 0x6040001b74c0 - "UIViewLayoutMarginsGuide", layoutFrame = {{0, 0}, {24, 44}}, owningView = <_UIButtonBarStackView: 0x7f94bd62d8d0; frame = (16 0; 24 44); layer = <CALayer: 0x604000237f40>>>
|   |   |   |   |   |   *UIButton:0x7f94bd51de30
|   |   |   |   |   |   |   UIImageView:0x7f94bd6210f0
|   |   |   |   |   *UILabel:0x7f94bd6298a0'Recommended for You'
|   |   |   |   +_UINavigationBarModernPromptView:0x7f94bd488da0
|   |   |   |   |   *UILabel:0x7f94bd4893d0
|   |   |   UIActivityIndicatorView:0x7f94bd531500
|   |   |   |   UIImageView:0x7f94bd507950

Legend:
    * - is laid out with auto layout
    + - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES
    • - layout engine host

欢迎任何反馈。谢谢

【问题讨论】:

    标签: ios storyboard interface-builder nslayoutconstraint


    【解决方案1】:

    这个问题背后的主要原因是,最初自动布局假设单元格的 contentView 有一个固定高度(直到正在计算动态高度)约束(必需),它与您自己的约束冲突并且它出现在这里 UIView-Encapsulated-Layout-Height ,您可以解决这是通过将 imageView 的底部约束的优先级降低为 999 而不是 1000(必需)

    解释

    您当前的宽度 = 375,纵横比 = 16 / 9

    那么 imageView 高度将 = (375*9)/16.0 = 210.9

    • 上11下11

    总计 = 211 + 11 + 11 = 233 > 80(估计行高)

    【讨论】:

    • 将底部约束设置为 999 为我做到了。
    【解决方案2】:

    问题是纵横比不会与您的其他约束冲突,只要它们不评估为 16:9。设置前导和尾随约束将评估为特定宽度,同时设置顶部和底部约束将评估为特定高度。宽度:高度的比例必须与您的纵横比相同,以免产生冲突。

    对此有多种解决方案。您可能想要的是用水平中心约束替换前导和尾随约束。这将使纵横比决定您的视图在单元格中居中时的宽度。

    更新: 为了阐明纵横比约束是如何工作的,它充当了高度和宽度之间的锁定,强制它们保持它们之间的固定比例。因此,如果您设置其中一个,纵横比约束将有效地为您设置另一个。因此,当您有纵横比约束时,不应同时设置宽度和高度约束。

    【讨论】:

    • 如果我这样做,则 UIImageView 的宽度没有限制。如果我添加一个宽度约束(UIImageView 和 superview 的宽度相等),问题就会返回...
    • 是的,不应该有宽度限制,因为当你设置了高度时,纵横比限制会为你设置宽度。
    • 这对我很有帮助 - 锚定到 centerX 而不是前导/尾随对我来说
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    • 2017-11-04
    • 2018-08-28
    相关资源
    最近更新 更多