更新imageView的高度约束时无法同时满足约束swift 4
Unable to simultaneously satisfy constraints when update height constraints of imageView swift 4
我有一个stack view
,如下图所示:
所以我以编程方式更改 image
的高度以使其适合从我的服务器下载的图像,如果没有图像,image
的高度限制将设置为零。
这是我的代码:
let imageUrl = URL(string :imageString)
if let data = try? Data(contentsOf: imageUrl!)
{
guard let actualImage: UIImage = UIImage(data: data) else{
print("No image!")
ImageView.image = nil
defaultImageHeightContrainst = ImageHeightContrainst.constant
ImageHeightContrainst.constant = 0
layoutIfNeeded()
return
}
let imageHeight = actualImage.size.height * actualImage.scale
print("imageHeight = \(imageHeight)")
defaultImageHeightContrainst = ImageHeightContrainst.constant
ImageHeightContrainst.constant = imageHeight
layoutIfNeeded()
//here display the image to the imageview
ImageView.kf.setImage(with: imageUrl)
}
使用上面的代码,图片高度是根据从internet.If下载的没有图片的实际图片高度缩放的,"image"部分也已经设置为0。
这是我的预期,但现在每当 "image" 高度变得更高以适合实际图像高度时,我都会遇到下面的错误
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:0x6080002868b0 UIImageView:0x7f9cbae59240.height == 50 (active)>",
"<NSLayoutConstraint:0x608000286bd0 UIView:0x7f9cbae5ad80.height == 1 (active)>",
"<NSLayoutConstraint:0x608000286d10 UIImageView:0x7f9cbae5b440.height == 458 (active)>",
"<NSLayoutConstraint:0x608000286f90 UIView:0x7f9cbae5bb50.height == 1 (active)>",
"<NSLayoutConstraint:0x6080002871c0 V:|-(0)-[UILabel:0x7f9cbae5b160] (active, names: '|':UIStackView:0x7f9cbae5af60 )>",
"<NSLayoutConstraint:0x608000287350 V:[UILabel:0x7f9cbae5b160]-(10)-[UIImageView:0x7f9cbae5b440] (active)>",
"<NSLayoutConstraint:0x6080002873a0 V:[UIImageView:0x7f9cbae5b440]-(10)-[UIStackView:0x7f9cbae5b670] (active)>",
"<NSLayoutConstraint:0x608000287580 V:[UIStackView:0x7f9cbae5b670]-(10)-[UIView:0x7f9cbae5bb50] (active)>",
"<NSLayoutConstraint:0x6080002875d0 V:[UIStackView:0x7f9cbae5c0f0]-(0)-| (active, names: '|':UIStackView:0x7f9cbae5af60 )>",
"<NSLayoutConstraint:0x608000287670 V:[UIView:0x7f9cbae5bb50]-(10)-[UIStackView:0x7f9cbae5c0f0] (active)>",
"<NSLayoutConstraint:0x6080002877b0 V:|-(10)-[UIImageView:0x7f9cbae59240] (active, names: '|':UITableViewCellContentView:0x7f9cbae5a0c0 )>",
"<NSLayoutConstraint:0x6080002878f0 V:[UIImageView:0x7f9cbae59240]-(8)-[UIView:0x7f9cbae5ad80] (active)>",
"<NSLayoutConstraint:0x6080002879e0 V:[UIStackView:0x7f9cbae5af60]-(10)-| (active, names: '|':UITableViewCellContentView:0x7f9cbae5a0c0 )>",
"<NSLayoutConstraint:0x608000287a80 V:[UIView:0x7f9cbae5ad80]-(8)-[UIStackView:0x7f9cbae5af60] (active)>",
"<NSLayoutConstraint:0x608000288c00 'UISV-canvas-connection' UIStackView:0x7f9cbae5c0f0.top == _UILayoutSpacer:0x6080001cd5c0'UISV-alignment-spanner'.top (active)>",
"<NSLayoutConstraint:0x608000288ca0 'UISV-canvas-connection' V:[_UILayoutSpacer:0x6080001cd5c0'UISV-alignment-spanner']-(0)-| (active, names: '|':UIStackView:0x7f9cbae5c0f0 )>",
"<NSLayoutConstraint:0x608000289970 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7f9cbae5a0c0.height == 476.5 (active)>"
)
在问之前,我已经检查了所有其他约束,都已设置 correctly.I 甚至禁用了所有可以更改 "image" 高度的代码,一旦禁用,就没有 problem.The 错误仅在我打算更改高度时出现。
我什至尝试在layoutIfNeeded()
之前添加ImageView.translatesAutoresizingMaskIntoConstraints = false
,但错误仍然存在。
那么更改图像高度以适合从服务器下载的实际图像的正确方法是什么?
考虑到最后一个约束说
"<NSLayoutConstraint:0x608000289970 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7f9cbae5a0c0.height == 476.5 (active)>"
我假设您在 UITableViewCell
中使用 stackView
来实现 tableView
中的自动高度单元格。如果我的假设是正确的,那么问题不在于 stackView
,也不在于 imageView
,而在于 UITableView
与 UITableViewAutomaticDimension
和自动布局的工作方式。如果布局按您的预期工作,并且警告是唯一让您烦恼的事情,请阅读以下内容。
因此在我看来,这是已知 "bug" 的结果 - tableView
设置的高度与自动布局计算的高度发生冲突。渲染单元格时,tableView
首先应用默认高度,计算自动布局高度,然后使用后者——至少看起来是这样。看我的。上面提到的约束 ('UIView-Encapsulated-Layout-Height'
) 是由后来消失的 UITableView
应用的约束。
这意味着您使用的约束可能没问题。只需将定义高度的约束之一设置为 priority = 999
(以便在它停用默认高度约束之前不会引起任何冲突)。最后会导致无论如何都会使用你的约束,所以不会造成任何布局问题。
例如,如果您将 stackView
限制为适合单元格的 contentView
,请将 stackView.bottomAnchor
设置为 contentView.bottomAnchor
,并将优先级设置为 999。如果您这样做了以编程方式布局,这可能是您的解决方案:
let bottomConstraint = tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
bottomConstraint.priority = UILayoutPriority(rawValue: 999)
NSLayoutConstraint.activate([
// rest of the constraints
stackView.topAnchor.constraint(equalTo: contentView.topAnchor),
stackView.leftAnchor.constraint(equalTo: contentView.leftAnchor),
stackView.rightAnchor.constraint(equalTo: contentView.rightAnchor),
bottomConstraint,
])
如果在故事板中进行布局,只需select故事板中的适当约束,并在属性检查器中将其优先级设置为 999(例如):
我有一个stack view
,如下图所示:
所以我以编程方式更改 image
的高度以使其适合从我的服务器下载的图像,如果没有图像,image
的高度限制将设置为零。
这是我的代码:
let imageUrl = URL(string :imageString)
if let data = try? Data(contentsOf: imageUrl!)
{
guard let actualImage: UIImage = UIImage(data: data) else{
print("No image!")
ImageView.image = nil
defaultImageHeightContrainst = ImageHeightContrainst.constant
ImageHeightContrainst.constant = 0
layoutIfNeeded()
return
}
let imageHeight = actualImage.size.height * actualImage.scale
print("imageHeight = \(imageHeight)")
defaultImageHeightContrainst = ImageHeightContrainst.constant
ImageHeightContrainst.constant = imageHeight
layoutIfNeeded()
//here display the image to the imageview
ImageView.kf.setImage(with: imageUrl)
}
使用上面的代码,图片高度是根据从internet.If下载的没有图片的实际图片高度缩放的,"image"部分也已经设置为0。
这是我的预期,但现在每当 "image" 高度变得更高以适合实际图像高度时,我都会遇到下面的错误
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:0x6080002868b0 UIImageView:0x7f9cbae59240.height == 50 (active)>",
"<NSLayoutConstraint:0x608000286bd0 UIView:0x7f9cbae5ad80.height == 1 (active)>",
"<NSLayoutConstraint:0x608000286d10 UIImageView:0x7f9cbae5b440.height == 458 (active)>",
"<NSLayoutConstraint:0x608000286f90 UIView:0x7f9cbae5bb50.height == 1 (active)>",
"<NSLayoutConstraint:0x6080002871c0 V:|-(0)-[UILabel:0x7f9cbae5b160] (active, names: '|':UIStackView:0x7f9cbae5af60 )>",
"<NSLayoutConstraint:0x608000287350 V:[UILabel:0x7f9cbae5b160]-(10)-[UIImageView:0x7f9cbae5b440] (active)>",
"<NSLayoutConstraint:0x6080002873a0 V:[UIImageView:0x7f9cbae5b440]-(10)-[UIStackView:0x7f9cbae5b670] (active)>",
"<NSLayoutConstraint:0x608000287580 V:[UIStackView:0x7f9cbae5b670]-(10)-[UIView:0x7f9cbae5bb50] (active)>",
"<NSLayoutConstraint:0x6080002875d0 V:[UIStackView:0x7f9cbae5c0f0]-(0)-| (active, names: '|':UIStackView:0x7f9cbae5af60 )>",
"<NSLayoutConstraint:0x608000287670 V:[UIView:0x7f9cbae5bb50]-(10)-[UIStackView:0x7f9cbae5c0f0] (active)>",
"<NSLayoutConstraint:0x6080002877b0 V:|-(10)-[UIImageView:0x7f9cbae59240] (active, names: '|':UITableViewCellContentView:0x7f9cbae5a0c0 )>",
"<NSLayoutConstraint:0x6080002878f0 V:[UIImageView:0x7f9cbae59240]-(8)-[UIView:0x7f9cbae5ad80] (active)>",
"<NSLayoutConstraint:0x6080002879e0 V:[UIStackView:0x7f9cbae5af60]-(10)-| (active, names: '|':UITableViewCellContentView:0x7f9cbae5a0c0 )>",
"<NSLayoutConstraint:0x608000287a80 V:[UIView:0x7f9cbae5ad80]-(8)-[UIStackView:0x7f9cbae5af60] (active)>",
"<NSLayoutConstraint:0x608000288c00 'UISV-canvas-connection' UIStackView:0x7f9cbae5c0f0.top == _UILayoutSpacer:0x6080001cd5c0'UISV-alignment-spanner'.top (active)>",
"<NSLayoutConstraint:0x608000288ca0 'UISV-canvas-connection' V:[_UILayoutSpacer:0x6080001cd5c0'UISV-alignment-spanner']-(0)-| (active, names: '|':UIStackView:0x7f9cbae5c0f0 )>",
"<NSLayoutConstraint:0x608000289970 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7f9cbae5a0c0.height == 476.5 (active)>"
)
在问之前,我已经检查了所有其他约束,都已设置 correctly.I 甚至禁用了所有可以更改 "image" 高度的代码,一旦禁用,就没有 problem.The 错误仅在我打算更改高度时出现。
我什至尝试在layoutIfNeeded()
之前添加ImageView.translatesAutoresizingMaskIntoConstraints = false
,但错误仍然存在。
那么更改图像高度以适合从服务器下载的实际图像的正确方法是什么?
考虑到最后一个约束说
"<NSLayoutConstraint:0x608000289970 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7f9cbae5a0c0.height == 476.5 (active)>"
我假设您在 UITableViewCell
中使用 stackView
来实现 tableView
中的自动高度单元格。如果我的假设是正确的,那么问题不在于 stackView
,也不在于 imageView
,而在于 UITableView
与 UITableViewAutomaticDimension
和自动布局的工作方式。如果布局按您的预期工作,并且警告是唯一让您烦恼的事情,请阅读以下内容。
因此在我看来,这是已知 "bug" 的结果 - tableView
设置的高度与自动布局计算的高度发生冲突。渲染单元格时,tableView
首先应用默认高度,计算自动布局高度,然后使用后者——至少看起来是这样。看我的'UIView-Encapsulated-Layout-Height'
) 是由后来消失的 UITableView
应用的约束。
这意味着您使用的约束可能没问题。只需将定义高度的约束之一设置为 priority = 999
(以便在它停用默认高度约束之前不会引起任何冲突)。最后会导致无论如何都会使用你的约束,所以不会造成任何布局问题。
例如,如果您将 stackView
限制为适合单元格的 contentView
,请将 stackView.bottomAnchor
设置为 contentView.bottomAnchor
,并将优先级设置为 999。如果您这样做了以编程方式布局,这可能是您的解决方案:
let bottomConstraint = tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
bottomConstraint.priority = UILayoutPriority(rawValue: 999)
NSLayoutConstraint.activate([
// rest of the constraints
stackView.topAnchor.constraint(equalTo: contentView.topAnchor),
stackView.leftAnchor.constraint(equalTo: contentView.leftAnchor),
stackView.rightAnchor.constraint(equalTo: contentView.rightAnchor),
bottomConstraint,
])
如果在故事板中进行布局,只需select故事板中的适当约束,并在属性检查器中将其优先级设置为 999(例如):