如何正确设置dynamic高度表格单元格的自动布局?

我尝试创build一个UITableViewCell并设置子视图如下:

 class MyCellView: UITableViewCell { private let ImageView = UIImageView() private let titleView = UILabel() override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) contentView.addSubview(ImageView) contentView.addSubview(titleView) ImageView.translatesAutoresizingMaskIntoConstraints = false ImageView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true ImageView.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true ImageView.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true ImageView.heightAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.6).isActive = true titleView.translatesAutoresizingMaskIntoConstraints = false titleView.topAnchor.constraint(equalTo: ImageView.bottomAnchor).isActive = true titleView.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true titleView.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true titleView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true titleView.numberOfLines = 0 titleView.text = " " // <-- *** please note this line } } 

而在表格视图中,我已经将它设置为使用dynamic高度:

 tableView.estimatedRowHeight = 80 tableView.rowHeight = UITableViewAutomaticDimension 

我的问题是,如果我没有在单元格中设置titleView的文本,比如我在单元格视图中注释最后一行:

 // titleView.text = " " 

我将从XCode获取约束错误。 但是,如果我设置文本,一切工作正常。

文本是从互联网上dynamic下载的,所以文本可能是空的。 除此之外,我可以把文本设置为空格,不知我在这里是否有误解? 如果我纠正某些内容,文本是否可以是空的(“”或“零”)?

同样,如果我完全删除关于titleView的代码,我只想在单元格中有一个UIImageView ,我发现单元格的高度没有扩大。 如何设置它,使我可以在单元格中有一个dynamic高度的图像?

编辑:约束错误:

 2017-12-22 15:35:34.715865+0800 MyProject[15774:733515] [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:0x60c000095450 V:|-(0)-[UIImageView:0x7ff40df0de90] (active, names: '|':UITableViewCellContentView:0x7ff40df0edc0 )>", "<NSLayoutConstraint:0x60c0000955e0 UIImageView:0x7ff40df0de90.height == 0.6*UITableViewCellContentView:0x7ff40df0edc0.width (active)>", "<NSLayoutConstraint:0x60c000095630 V:[UIImageView:0x7ff40df0de90]-(0)-[UILabel:0x7ff40df0e0c0] (active)>", "<NSLayoutConstraint:0x60c0000957c0 UILabel:0x7ff40df0e0c0.bottom == UITableViewCellContentView:0x7ff40df0edc0.bottom (active)>", "<NSLayoutConstraint:0x60c000096210 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7ff40df0edc0.height == 248.333 (active)>", "<NSLayoutConstraint:0x60c000095ea0 'UIView-Encapsulated-Layout-Width' UITableViewCellContentView:0x7ff40df0edc0.width == 414 (active)>" ) Will attempt to recover by breaking constraint <NSLayoutConstraint:0x60c000095630 V:[UIImageView:0x7ff40df0de90]-(0)-[UILabel:0x7ff40df0e0c0] (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. 

  • 如果你想避免警告,请尝试下面的代码

     class MyCellView: UITableViewCell { private let ImageView = UIImageView() private let titleView = UILabel() override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) contentView.addSubview(ImageView) contentView.addSubview(titleView) ImageView.translatesAutoresizingMaskIntoConstraints = false ImageView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true ImageView.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true ImageView.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true let heightConstraint = ImageView.heightAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.6) heightConstraint.priority = UILayoutPriority.defaultLow heightConstraint.isActive = true titleView.translatesAutoresizingMaskIntoConstraints = false titleView.topAnchor.constraint(equalTo: ImageView.bottomAnchor).isActive = true titleView.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true titleView.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true titleView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true titleView.numberOfLines = 0 // titleView.text = " " } } 
  • 如果您完全删除了关于titleView的代码,并希望在单元格中具有dynamic高度的UIImageViewbottomAnchor添加bottomAnchor约束

     class MyCellView: UITableViewCell { private let ImageView = UIImageView() private let titleView = UILabel() override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) contentView.addSubview(ImageView) contentView.addSubview(titleView) ImageView.translatesAutoresizingMaskIntoConstraints = false ImageView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true ImageView.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true ImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true ImageView.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true let heightConstraint = ImageView.heightAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.6) heightConstraint.priority = UILayoutPriority.defaultLow heightConstraint.isActive = true } } 

看起来这是一个已知“bug”的结果 – tableView设置的高度和自动布局计算的高度有碰撞。 当渲染单元格时, tableView首先应用默认高度,计算自动布局高度,然后使用后者 – 至less看起来如此。 看到我的问题 。

这意味着你使用的限制是可以的(至less它们对我来说似乎是这样)。 只需将其中一个定义高度的约束设置为优先级= 999(这样,直到它停用默认的高度约束,它不会引起任何冲突)。 最终会导致使用你的约束,所以不会造成任何麻烦。

PS:注意那个imageView高度限制:

 ImageView.heightAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.6).isActive = true 

如果你想省略图像(因此使用height = 0来渲染),那也会给你带来麻烦(再次,降低优先级可能会让你想要的地方)。 如果图像总是在那里,那么不要介意我的PS :)。