具有相对约束的自动布局不影响systemLayoutSizeFittingSize:用于UITableViewCell

mlu*_*own 4 objective-c uitableview ios autolayout

我有一个UITableView动态高度UITableViewCells,我正在使用自动布局来计算高度,根据这个主题的优秀答案.到现在为止还挺好.

我正在调整应用程序以使用更大的iPhone(6和6 Plus)屏幕尺寸,这大部分非常简单.

但是,在我的一些单元格中,我有一个想要跨越单元格整个宽度的图像,我希望图像的高度与图像的宽度成正比(0.55*宽度,具体而言).到目前为止,基于iPhone 6/6 Plus之前的标准320px纵向表视图宽度,我在自动布局约束中硬编码了图像的宽度和高度.

我认为像这样添加相对高度约束会很简单(我正在使用PureLayout):

[self.myImage autoMatchDimension:ALDimensionHeight 
                     toDimension:ALDimensionWidth 
                          ofView:self 
                  withMultiplier:0.55f 
                        relation:NSLayoutRelationGreaterThanOrEqual];
Run Code Online (Sandbox Code Playgroud)

如果您不熟悉PureLayout,则转换为调用

[NSLayoutConstraint constraintWithItem: attribute: relatedBy: toItem: attribute: multiplier: constant:0.0f]

还有其他约束将它的边缘固定到superview,即UITableViewCellcontentView.

但是,当我调用systemLayoutSizeFittingSize:单元格的contentView时,它似乎完全忽略了相对高度约束,并且得到的单元格高度太小而不适合图像.

如果我设置显式高度约束而不是相对高度约束,则没有问题.类似地,如果我子类UIImageView并返回显式大小intrinsicContentSize,则没有问题.

我甚至在我的UIImageView子类中尝试了以下内容:

- (void) layoutSubviews {
    [super layoutSubviews];    
    self.intrinsicSizeForAutolayout = self.frame.size;    
    [super layoutSubviews];
}

- (CGSize)intrinsicContentSize {
    return self.intrinsicSizeForAutolayout;
}
Run Code Online (Sandbox Code Playgroud)

其中intrinsicSizeForAutolayout是我为此目的定义的属性.我认为这可能preferredMaxLayoutWidthUILabels的设置解决类似问题的方式类似.

但不是.它不起作用.

看起来我几乎没有办法使用丑陋的屏幕宽度检查代码来根据屏幕宽度有条件地设置一个固定的高度约束,这是我真正想要避免的,因为它首先打破了使用自动布局的目的.

smi*_*org 7

contentView默认情况下,单元格的宽度没有任何约束(其宽度仅在SDK添加到表视图时由SDK设置),因此当您调用systemLayoutSizeFittingSize:它时,约束求解器假定将宽度压缩为有效在尝试找到有效的解决方案时需要很多,这当然会导致错误的高度.

要解决此问题,您可以添加一个约束contentView,将其宽度固定为最终的单元格/表视图宽度.这是有效的,因为该约束被纳入单元格大小布局传递中,并导致systemLayoutSizeFittingSize:按预期工作.

使用PureLayout,我建议做类似的事情:

[UIView autoSetPriority:UILayoutPriorityRequired - 1 forConstraints:^{
    [cell.contentView autoSetDimension:ALDimensionWidth toSize:CGRectGetWidth(tableView.bounds)];
}];
Run Code Online (Sandbox Code Playgroud)

请注意,为约束设置小于Required的优先级并不是一个坏主意,因为这只是为了帮助调整大小操作,并且如果它被破坏,您不希望出现异常(可能是未来的SDK更改)表视图单元格如何工作).但这可能并不重要.

此外,像往常一样,您可能希望确保此约束仅添加一次(不是每次都tableView:heightForRowAtIndexPath:被调用) - 这应该很容易.

请参阅此处以获取示例项目的fork的特定解决方案:https://gist.github.com/smileyborg/0a2082a4d26fcc7fde4d