我有一个UITableView在iOS 8下运行,我在故事板中使用约束的自动单元格高度。

我的一个单元格包含一个UITextView,我需要它根据用户输入收缩和展开-点击收缩/展开文本。

我通过在文本视图中添加一个运行时约束,并在响应用户事件时改变约束上的常数来做到这一点:

-(void)collapse:(BOOL)collapse; {

    _collapsed = collapse;

    if(collapse)
        [_collapsedtextHeightConstraint setConstant: kCollapsedHeight]; // 70.0
    else
        [_collapsedtextHeightConstraint setConstant: [self idealCellHeightToShowFullText]];

    [self setNeedsUpdateConstraints];

}

无论何时我这样做,我包装在tableView更新和调用[tableView setNeedsUpdateConstraints]:

[tableView beginUpdates];

[_briefCell collapse:!_showFullBriefText];

[tableView setNeedsUpdateConstraints];
// I have also tried 
// [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
// with exactly the same results.

[tableView endUpdates];

当我这样做的时候,我的单元格确实会扩展(并在做的时候动画),但我得到一个约束警告:

2014-07-31 13:29:51.792 OneFlatEarth[5505:730175] 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:0x7f94dced2b60 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'(388)]>",

    "<NSLayoutConstraint:0x7f94dced2260 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...']-(15)-|   (Names: '|':UITableViewCellContentView:0x7f94de5773a0 )>",

    "<NSLayoutConstraint:0x7f94dced2350 V:|-(6)-[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...']   (Names: '|':UITableViewCellContentView:0x7f94de5773a0 )>",

    "<NSLayoutConstraint:0x7f94dced6480 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7f94de5773a0(91)]>"
 )

Will attempt to recover by breaking constraint 

<NSLayoutConstraint:0x7f94dced2b60 V:[UITextView:0x7f94d9b2b200'Brief text: Lorem Ipsum i...'(388)]>

388是我计算的高度,UITextView上的其他约束是我从Xcode/IB中得到的。

最后一个是困扰我-我猜uiview - encapsulation - layout - height是计算单元格的高度时,它是第一次渲染-(我设置我的UITextView高度>= 70.0),但它似乎不正确,这个派生约束然后驳回更新用户cnstraint。

更糟糕的是,尽管布局代码说它试图打破我的高度限制,但它并没有-它继续重新计算单元格的高度,一切都按照我想要的方式绘制。

所以,什么是NSLayoutConstraint UIView-Encapsulated-Layout-Height(我猜它是计算的高度自动单元格大小),我应该如何去迫使它重新计算干净?


当前回答

我能够通过在约束中的一个值上指定优先级来消除警告,警告消息说它必须打破(下面是“将试图通过打破约束来恢复”)。似乎只要我将优先级设置为大于49的值,警告就会消失。

对我来说,这意味着改变我的约束,警告说它试图打破:

@“V:|[contentLabel]-[quoteeLabel]|”

to:

@“V:|-0@500-[内容标签]-[quoteeLabel]|”

事实上,我可以为约束的任何元素添加优先级,它都可以工作。哪一个似乎都不重要。我的单元格最终达到了适当的高度,并且没有显示警告。Roger,以你为例,尝试在388高度值约束(例如388@500)后面添加@500。

我不完全确定为什么会这样,但我做了一些调查。在NSLayoutPriority枚举中,看起来NSLayoutPriorityFittingSizeCompression优先级是50。该优先级级别的文档说:

当你发送一个fittingSize消息给一个视图时,最小的尺寸 足够大,可以计算视图的内容。这是 视图希望尽可能小的优先级级别 计算。相当低。这样做一般是不合适的 在这个优先级上做一个约束。你想要更高还是 低。

引用的fittingSize消息的文档如下:

满足它所持有的约束的视图的最小大小。 (只读) AppKit将此属性设置为视图可用的最佳大小, 考虑到它及其子视图所拥有的所有约束和 满足使视图尽可能小的偏好。的 此属性中的大小值从不为负。

我还没有深入研究,但这似乎与问题所在有关。

其他回答

我能够通过在约束中的一个值上指定优先级来消除警告,警告消息说它必须打破(下面是“将试图通过打破约束来恢复”)。似乎只要我将优先级设置为大于49的值,警告就会消失。

对我来说,这意味着改变我的约束,警告说它试图打破:

@“V:|[contentLabel]-[quoteeLabel]|”

to:

@“V:|-0@500-[内容标签]-[quoteeLabel]|”

事实上,我可以为约束的任何元素添加优先级,它都可以工作。哪一个似乎都不重要。我的单元格最终达到了适当的高度,并且没有显示警告。Roger,以你为例,尝试在388高度值约束(例如388@500)后面添加@500。

我不完全确定为什么会这样,但我做了一些调查。在NSLayoutPriority枚举中,看起来NSLayoutPriorityFittingSizeCompression优先级是50。该优先级级别的文档说:

当你发送一个fittingSize消息给一个视图时,最小的尺寸 足够大,可以计算视图的内容。这是 视图希望尽可能小的优先级级别 计算。相当低。这样做一般是不合适的 在这个优先级上做一个约束。你想要更高还是 低。

引用的fittingSize消息的文档如下:

满足它所持有的约束的视图的最小大小。 (只读) AppKit将此属性设置为视图可用的最佳大小, 考虑到它及其子视图所拥有的所有约束和 满足使视图尽可能小的偏好。的 此属性中的大小值从不为负。

我还没有深入研究,但这似乎与问题所在有关。

我在集合视图单元格中遇到了类似的问题。

我通过降低链接到单元格底部的最终约束的优先级来解决这个问题(从视图的顶部到底部的链中的最后一个约束-这最终决定了它的高度)到999。

细胞的高度是正确的,警告就消失了。

TableView在indexPath从委托获取单元格的高度。 然后从cellForRowAtIndexPath获取cell:

top (10@1000)
    cell
bottom (0@1000)

如果cell.contentView。height:0 //<-> (uiview - encapsulation - layout - height: 0@1000) top(10@1000)冲突(uiview - encapsulation - layout - height:0@1000),

因为它们的优先级是1000。 我们需要在uiview - encapsulation - layout - height的优先级下设置top priority。

我收到的信息是这样的:

无法同时满足约束条件… ... ... ... NSLayoutConstraint: 0 x7fe74bdf7e50 UIView-Encapsulated-Layout-Height” V: [UITableViewCellContentView: 0 x7fe75330c5c0 (21.5)] ... ... 会试图通过打破约束来恢复吗 x7fe0f9b1e090 NSLayoutConstraint: 0 x7fe0f9b200c0 UITableViewCellContentView: 0。bottomMargin == UILabel:0x7fe0f9b1e970.bottom

我使用一个自定义的UITableViewCell和UITableViewAutomaticDimension的高度。我还实现了estimatedhighightforrowatindex:方法。

给我带来问题的约束条件是这样的

[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[title]-|" options:0 metrics:nil views:views];

将约束改为this将解决问题,但就像另一个答案一样,我觉得这是不正确的,因为它降低了我希望被要求的约束的优先级:

[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-6@999-[title]-6@999-|" options:0 metrics:nil views:views];

然而,我注意到的是,如果我实际上只是删除优先级,这也是有效的,我不会得到破坏约束日志:

[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-6-[title]-6-|" options:0 metrics:nil views:views];

|-6-[title]-6-|和|-[title-|之间的区别是什么,这有点神秘。但是,指定大小对我来说不是问题,它消除了日志,而且我不需要降低所需约束的优先级。

No one answered it how to solve the case in storyboard. You have the case of mine, top bottom constraint with fixed height with priority 1000. That is why, when first time loading , as the table view cell height is 0, tries to set the element with the fixed height, causing a constraint conflict. (I am trying to insert 40 pixel in a 0 pixel height area, so compiler tries discarding the 40 pixel height). Once the tableview loaded, it will not generate (Like pop back to the tableview or switching tab bar tab)

所以将优先级从必需的@1000更改为高@750或低@250。第一次加载时,不考虑低优先级,然后在layoutSubviews()中调整所有约束的大小