我有一个UITableViewCell
和一个UILabel
和一个UIImageView
。图片可以显示或隐藏。
UILabel
的结尾部分有两个约束,一个约束(a)与UIImageView
等于8,另一个约束(b)大于或等于8,右边单元格的边缘。我保留了第一个(a)的引用,如果有声音,我将激活或取消激活约束。
这是我的代码:
class MyTableViewCell: UITableViewCell {
@IBOutlet weak var label: UILabel?
@IBOutlet weak var icon: UIImageView?
@IBOutlet weak var spaceBetweenIconAndLabelConstraint: NSLayoutConstraint?
override func awakeFromNib() {
super.awakeFromNib()
icon?.image = UIImage(named: "sound")
}
func config(with name: String, hasSound: Bool) {
label?.text = name
configSound(hasSound)
}
private func configSound(_ hasSound: Bool) {
icon?.isHidden = !hasSound
spaceBetweenIconAndLabelConstraint?.isActive = hasSound
}
}
我有几个带有可见声音图标的单元格,很多没有。这是特定单元格首次出现时的样子:
第二次返回屏幕时的外观:
我确实知道问题出在重复使用的单元中。但是我不明白如何防止这种行为。我尝试这样做:
override func prepareForReuse() {
configSound(true)
}
在重新使用单元格之前重新激活约束,但这不起作用。
答案 0 :(得分:4)
我认为问题在于您使用weak
引用作为约束。在这种情况下,约束第一次将其isActive
属性设置为false
时便被删除。由此可见nil
,无法将其重新激活。
解决方案:删除关键字weak
,以此作为强有力的参考。
@IBOutlet var spaceBetweenIconAndLabelConstraint: NSLayoutConstraint!
答案 1 :(得分:2)
有两种以上的方法可以做到这一点。如果您的目标是iOS 9+,则强烈建议您使用堆栈视图。它们完全可以满足您的需求,而无需手动添加/删除/激活/停用约束。
用户界面如下所示:
水平堆栈视图(从8到前导,从8到尾随,间距等于8) 内: 1.在左侧标签上 2.在右侧的图标图像视图上(可选地包装在iconContainer视图中,或仅设置AspectFit)
更新代码:
class MyTableViewCellWithStackView: UITableViewCell {
@IBOutlet weak var label: UILabel?
@IBOutlet weak var iconContainer: UIView?
func config(with name: String, hasSound: Bool) {
label?.text = name
iconContainer?.isHidden = !hasSound
}
}
无论何时隐藏icon / iconContainer,堆栈视图都会自动更新并相应地填充空间。
如果您不能使用堆栈视图(首选),可以尝试以下操作:
class MyTableViewCell: UITableViewCell {
@IBOutlet weak var label: UILabel?
@IBOutlet weak var icon: UIImageView?
@IBOutlet weak var spaceBetweenIconAndLabelConstraint: NSLayoutConstraint?
override func awakeFromNib() {
super.awakeFromNib()
icon?.image = UIImage(named: "sound")
}
func config(with name: String, hasSound: Bool) {
label?.text = name
configSound(hasSound)
}
private func configSound(_ hasSound: Bool) {
icon?.isHidden = !hasSound
guard hasSound else {
spaceBetweenIconAndLabelConstraint?.isActive = false
return
}
guard let icon = icon, let label = label else { return }
let constraint = label.rightAnchor
.constraint(equalTo: icon.leftAnchor, constant: 8)
constraint.isActive = true
spaceBetweenIconAndLabelConstraint = constraint
}
}