在 iOS "Unable to simultaneously satisfy constraints" 中获取 UI 布局的警告
Getting Warning for UI Layout in iOS "Unable to simultaneously satisfy constraints"
我已经以编程方式创建了 UITableviewCell 并尝试在 table 视图中加载
Cell 只有一个 imageView 和 UIlabel.
虽然 UI 看起来不错,但我看到了这个警告:
无法同时满足约束条件。
可能至少以下列表中的约束之一是您不想要的。
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:0x60000147f200 V:|-(0)-[UIView:0x7f897ea24a00] (active, names: '|':SampleTest.MemesTableViewCell:0x7f897ea2aaf0 )>",
"<NSLayoutConstraint:0x60000147f2f0 UIView:0x7f897ea24a00.bottom == SampleTest.MemesTableViewCell:0x7f897ea2aaf0.bottom (active)>",
"<NSLayoutConstraint:0x60000147f570 V:|-(10)-[UIImageView:0x7f897ea18170] (active, names: '|':UIView:0x7f897ea24a00 )>",
"<NSLayoutConstraint:0x60000147f110 UIImageView:0x7f897ea18170.height == 80 (active)>",
"<NSLayoutConstraint:0x60000147eb70 UIImageView:0x7f897ea18170.bottom == UIView:0x7f897ea24a00.bottom - 20 (active)>",
"<NSLayoutConstraint:0x60000147f4d0 'UIView-Encapsulated-Layout-Height' SampleTest.MemesTableViewCell:0x7f897ea2aaf0.height == 44 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x60000147f110 UIImageView:0x7f897ea18170.height == 80 (active)>
我的代码:
import UIKit
class MemesTableViewCell : UITableViewCell {
var contentHolderView : UIView = {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
private let nameLabel = UILabel()
var memeImageView = UIImageView()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupView() {
contentHolderView.backgroundColor = UIColor.red
addSubview(contentHolderView)
contentHolderView.addSubview(nameLabel)
contentHolderView.addSubview(memeImageView)
nameLabel.translatesAutoresizingMaskIntoConstraints = false
memeImageView.translatesAutoresizingMaskIntoConstraints = false
memeImageView.contentMode = .scaleAspectFit
NSLayoutConstraint.activate([
//layout contentView
contentHolderView.topAnchor.constraint(equalTo: self.topAnchor,constant: 0),
contentHolderView.bottomAnchor.constraint(equalTo: bottomAnchor,constant: 0),
contentHolderView.leadingAnchor.constraint(equalTo: leadingAnchor,constant: 0),
contentHolderView.trailingAnchor.constraint(equalTo: trailingAnchor,constant: 0),
memeImageView.topAnchor.constraint(equalTo: contentHolderView.topAnchor, constant: 10),
memeImageView.leadingAnchor.constraint(equalTo: contentHolderView.leadingAnchor, constant: 10),
memeImageView.widthAnchor.constraint(equalToConstant: 80),
memeImageView.heightAnchor.constraint(equalToConstant: 80),
nameLabel.leadingAnchor.constraint(equalTo: memeImageView.trailingAnchor, constant: 10),
nameLabel.topAnchor.constraint(equalTo: contentHolderView.topAnchor, constant: 12)
])
if let lastView = contentHolderView.getTheLastAddedView() {
lastView.bottomAnchor.constraint(equalTo: contentHolderView.bottomAnchor, constant: -20).isActive = true
}
self.layoutIfNeeded()
}
}
extension UIView {
func getTheLastAddedView()->UIView?{
if let lastView = self.subviews.last{
return lastView
}
return nil
}
}
我想知道如何修复此警告?
这是使用带有嵌入视图的单元格时的常见情况。
如您所见,UI 结果 看起来 很好——因为 auto-layout 将 尝试通过打破约束来恢复,然后是 re-establishes 约束。
要消除警告,请为最终定义高度的约束赋予 less-than-required 优先级。
因此,将 setupView()
函数的末尾更改为:
if let lastView = contentHolderView.getTheLastAddedView() {
let c = lastView.bottomAnchor.constraint(equalTo: contentHolderView.bottomAnchor, constant: -20)
c.priority = .required - 1
c.isActive = true
//lastView.bottomAnchor.constraint(equalTo: contentHolderView.bottomAnchor, constant: -20).isActive = true
}
// this is not needed
//self.layoutIfNeeded()
附带说明一下,不应将单元格的子视图添加到或限制到单元格本身。您应该改用单元格的 .contentView
:
contentView.addSubview(contentHolderView)
然后:
NSLayoutConstraint.activate([
//layout contentView
contentHolderView.topAnchor.constraint(equalTo: contentView.topAnchor,constant: 0),
contentHolderView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor,constant: 0),
contentHolderView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor,constant: 0),
contentHolderView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor,constant: 0),
我已经以编程方式创建了 UITableviewCell 并尝试在 table 视图中加载 Cell 只有一个 imageView 和 UIlabel.
虽然 UI 看起来不错,但我看到了这个警告:
无法同时满足约束条件。 可能至少以下列表中的约束之一是您不想要的。
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:0x60000147f200 V:|-(0)-[UIView:0x7f897ea24a00] (active, names: '|':SampleTest.MemesTableViewCell:0x7f897ea2aaf0 )>",
"<NSLayoutConstraint:0x60000147f2f0 UIView:0x7f897ea24a00.bottom == SampleTest.MemesTableViewCell:0x7f897ea2aaf0.bottom (active)>",
"<NSLayoutConstraint:0x60000147f570 V:|-(10)-[UIImageView:0x7f897ea18170] (active, names: '|':UIView:0x7f897ea24a00 )>",
"<NSLayoutConstraint:0x60000147f110 UIImageView:0x7f897ea18170.height == 80 (active)>",
"<NSLayoutConstraint:0x60000147eb70 UIImageView:0x7f897ea18170.bottom == UIView:0x7f897ea24a00.bottom - 20 (active)>",
"<NSLayoutConstraint:0x60000147f4d0 'UIView-Encapsulated-Layout-Height' SampleTest.MemesTableViewCell:0x7f897ea2aaf0.height == 44 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x60000147f110 UIImageView:0x7f897ea18170.height == 80 (active)>
我的代码:
import UIKit
class MemesTableViewCell : UITableViewCell {
var contentHolderView : UIView = {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
private let nameLabel = UILabel()
var memeImageView = UIImageView()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupView() {
contentHolderView.backgroundColor = UIColor.red
addSubview(contentHolderView)
contentHolderView.addSubview(nameLabel)
contentHolderView.addSubview(memeImageView)
nameLabel.translatesAutoresizingMaskIntoConstraints = false
memeImageView.translatesAutoresizingMaskIntoConstraints = false
memeImageView.contentMode = .scaleAspectFit
NSLayoutConstraint.activate([
//layout contentView
contentHolderView.topAnchor.constraint(equalTo: self.topAnchor,constant: 0),
contentHolderView.bottomAnchor.constraint(equalTo: bottomAnchor,constant: 0),
contentHolderView.leadingAnchor.constraint(equalTo: leadingAnchor,constant: 0),
contentHolderView.trailingAnchor.constraint(equalTo: trailingAnchor,constant: 0),
memeImageView.topAnchor.constraint(equalTo: contentHolderView.topAnchor, constant: 10),
memeImageView.leadingAnchor.constraint(equalTo: contentHolderView.leadingAnchor, constant: 10),
memeImageView.widthAnchor.constraint(equalToConstant: 80),
memeImageView.heightAnchor.constraint(equalToConstant: 80),
nameLabel.leadingAnchor.constraint(equalTo: memeImageView.trailingAnchor, constant: 10),
nameLabel.topAnchor.constraint(equalTo: contentHolderView.topAnchor, constant: 12)
])
if let lastView = contentHolderView.getTheLastAddedView() {
lastView.bottomAnchor.constraint(equalTo: contentHolderView.bottomAnchor, constant: -20).isActive = true
}
self.layoutIfNeeded()
}
}
extension UIView {
func getTheLastAddedView()->UIView?{
if let lastView = self.subviews.last{
return lastView
}
return nil
}
}
我想知道如何修复此警告?
这是使用带有嵌入视图的单元格时的常见情况。
如您所见,UI 结果 看起来 很好——因为 auto-layout 将 尝试通过打破约束来恢复,然后是 re-establishes 约束。
要消除警告,请为最终定义高度的约束赋予 less-than-required 优先级。
因此,将 setupView()
函数的末尾更改为:
if let lastView = contentHolderView.getTheLastAddedView() {
let c = lastView.bottomAnchor.constraint(equalTo: contentHolderView.bottomAnchor, constant: -20)
c.priority = .required - 1
c.isActive = true
//lastView.bottomAnchor.constraint(equalTo: contentHolderView.bottomAnchor, constant: -20).isActive = true
}
// this is not needed
//self.layoutIfNeeded()
附带说明一下,不应将单元格的子视图添加到或限制到单元格本身。您应该改用单元格的 .contentView
:
contentView.addSubview(contentHolderView)
然后:
NSLayoutConstraint.activate([
//layout contentView
contentHolderView.topAnchor.constraint(equalTo: contentView.topAnchor,constant: 0),
contentHolderView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor,constant: 0),
contentHolderView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor,constant: 0),
contentHolderView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor,constant: 0),