iosswiftuitableviewnslayoutconstraintprepareforreuse

NSLayoutConstraints is not respected in UITableViewCell


I have a UITableViewCell with an UILabel and an UIImageView. The image can be visible or hidden.

Here is my storyboard: storyboard screenshot

There's two constraints on the trailing part of the UILabel, one (a) that is equal to 8 with the UIImageView, another one (b) that is greater or equal to 8 with the right margin of the cell. I keep a reference of the first one (a), and I activate or deactivate the constraint if there is or not some sound.

Here is my code:

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
    }
}

I have a few cells with the sound icon visible, a lot without. Here is what it looks like when a specific cell first appears:

good behaviour

And what it looks like when it comes back on the screen a second time:

bad behaviour

I do understand the problem is coming from the cell being reused. But I don't understand how I can prevent this behaviour. I tried to do:

override func prepareForReuse() {
    configSound(true)
}

to reactivate the constraint before reusing the cell, but it doesn't work.


Solution

  • I think the problem is the fact that you use a weak reference for your constraint. In that case the constraint gets removed as soon as its isActive property is set to false for the first time. From that on it is nil and can't be reactivated.

    Solution: Use a strong reference by removing the weak keyword.

    @IBOutlet var spaceBetweenIconAndLabelConstraint: NSLayoutConstraint!