我有一个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(我猜它是计算的高度自动单元格大小),我应该如何去迫使它重新计算干净?


当前回答

设置该视图。translatesAutoresizingMaskIntoConstraints = NO;应该能解决这个问题。

其他回答

当使用UITableViewAutomaticDimension并在单元格内的视图上更改高度约束时,我有这个错误。

我最终发现这是由于约束常数值没有四舍五入到最近的整数。

let neededHeight = width / ratio // This is a CGFloat like 133.2353
constraintPictureHeight.constant = neededHeight // Causes constraint error
constraintPictureHeight.constant = ceil(neededHeight) // All good!

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

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

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

to:

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

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

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

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

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

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

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

我能够解决这个错误通过删除一个假cell.layoutIfNeeded(),我在我的tableView的cellForRowAt方法。

调整文本视图以适应其内容,并将高度约束常数更新为结果高度,为我固定了uiview - encapsulation - layout - height约束冲突,例如:

[self.textView sizeToFit];
self.textViewHeightConstraint.constant = self.textView.frame.size.height;

我也有同样的问题。对我来说,误差是0.5像素。

2020-08-06 21:33:20.947369+0530 DemoNestedTableView[4181:384993] [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:0x600000a3abc0 UICollectionView:0x7fde0780c200.height == 326   (active)>",
        "<NSLayoutConstraint:0x600000a3ae40 V:|-(0)-[UICollectionView:0x7fde0780c200]   (active, names: '|':UITableViewCellContentView:0x7fde05e0cb10 )>",
        "<NSLayoutConstraint:0x600000a3af30 V:[UICollectionView:0x7fde0780c200]-(0)-|   (active, names: '|':UITableViewCellContentView:0x7fde05e0cb10 )>",
        "<NSLayoutConstraint:0x600000a2a4e0 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7fde05e0cb10.height == 326.5   (active)>"
    )

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x600000a3abc0 UICollectionView:0x7fde0780c200.height == 326   (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.

只要加上这个就行了。

self.tableView.separatorStyle = .none