NSLayoutConstraints не соблюдается в UITableViewCell - PullRequest
0 голосов
/ 09 декабря 2018

У меня есть UITableViewCell с UILabel и UIImageView.Изображение может быть видимым или скрытым.

Вот моя раскадровка: storyboard screenshot

Есть два ограничения на задней части UILabel, одно (a), который равен 8 с UIImageView, другой (b), который больше или равен 8 с правым полем ячейки.Я сохраняю ссылку на первый (а) и активирую или деактивирую ограничение, если есть или нет какой-либо звук.

Вот мой код:

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

У меня естьнесколько ячеек с видимой иконкой звука, много без.Вот как это выглядит, когда конкретная ячейка появляется впервые:

good behaviour

И как она выглядит, когда снова появляется на экране:

bad behaviour

Я понимаю, что проблема связана с повторным использованием ячейки.Но я не понимаю, как я могу предотвратить это поведение.Я попытался сделать:

override func prepareForReuse() {
    configSound(true)
}

, чтобы повторно активировать ограничение перед повторным использованием ячейки, но оно не работает.

Ответы [ 2 ]

0 голосов
/ 09 декабря 2018

Есть более двух способов сделать это.Если вы ориентируетесь на 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
    }
}
0 голосов
/ 09 декабря 2018

Я думаю, что проблема в том, что вы используете weak ссылку для вашего ограничения.В этом случае ограничение снимается, как только его свойство isActive устанавливается в false в первый раз.С этого момента он является nil и не может быть повторно активирован.

Решение: используйте надежную ссылку, удалив ключевое слово weak.

@IBOutlet var spaceBetweenIconAndLabelConstraint: NSLayoutConstraint!
...