4

我有一个UITableViewCell与一个UILabel和一个UIImageView。图像可以是可见的或隐藏的。

这是我的故事板: 故事板截图

的尾部有两个约束UILabel,一个 (a) 等于 8 与UIImageView,另一个 (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)
}

在重用单元格之前重新激活约束,但它不起作用。

4

2 回答 2

8

我认为问题在于您使用weak参考作为约束的事实。在这种情况下,一旦第一次将其isActive属性设置为,约束就会被删除。false从那以后它是nil并且不能被重新激活。

weak解决方案:通过删除关键字来使用强引用。

@IBOutlet var spaceBetweenIconAndLabelConstraint: NSLayoutConstraint!
于 2018-12-09T19:18:51.167 回答
4

有两种以上的方法可以做到这一点。如果您的目标是 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
    }
}

每当您隐藏图标/图标容器时,堆栈视图都会自行更新并相应地填充空间。

如果你不能使用堆栈视图(首选),你可以试试这个:

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
    }
}
于 2018-12-09T20:52:31.630 回答