Невозможно удалить / сделать неактивным NSLAyoutConstraint - PullRequest
0 голосов
/ 05 февраля 2020

У меня есть UitableView, отображающий комментарии пользователей. В каждой из этих ячеек я также вставляю другой UITableView, который показывает ответы на эти комментарии (если есть). Когда я нажимаю на кнопку «ответы», я хотел бы изменить высоту этой таблицы ответов (по умолчанию 0) на 1000, чтобы отобразить список ответов, представленный этим внутренним UITableView. Я попытался деактивировать ограничение высоты по умолчанию (0) для этого внутреннего UITableView безуспешно, и я не знаю почему.

Мое текущее приложение: enter image description here

Ниже приведен код для UITableViewCell для этого внешнего UITableView

class CommentTableViewCell: UITableViewCell {

var nameLabel: UILabel = {
    let label = UILabel()
    label.font = .boldSystemFont(ofSize: 11)
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()
var imgView: UIImageView = {
    let view = UIImageView()
    view.backgroundColor = UIColor.black
    view.contentMode = .scaleAspectFit
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()
var replyLabel: UILabel = {
    let label = UILabel()
    label.text = "Reply"
    label.textColor = UIColor.appGrayForButtonTitles
    label.font = UIFont.systemFont(ofSize: 11)
    label.isUserInteractionEnabled = true
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()

var numRepliesLabel: UILabel = {
    let label = UILabel()
    label.font = .boldSystemFont(ofSize: 11)
    label.textColor = UIColor.app0946BF
    label.textAlignment = .right
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()
var repliesTextLabel: UILabel = {
    let label = UILabel()
    label.text = "Replies"
    label.font = .boldSystemFont(ofSize: 11)
    label.textColor = UIColor.app0946BF
    label.isUserInteractionEnabled = true
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()
var timeReplyContainer: UIView = {
    let view = UIView()
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()
var timeAgoLabel: UILabel = {
    let label = UILabel()
    label.text = "1 hr"
    label.textColor = UIColor.appGrayLight
    label.font = UIFont.systemFont(ofSize: 11)
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()
var timeTextLabel: UILabel = {
    let label = UILabel()
    label.textColor = UIColor.appGrayLight
    label.text = "ago"
    label.font = UIFont.systemFont(ofSize: 11)
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()
var repliesContainer: UIView = {
    let view = UIView()
    view.backgroundColor = UIColor.yellow
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
}()
var cellIndexPath: IndexPath?
var commentLabel: LabelWithPadding!
var repliesTableView: RepliesToCommentsTableView!
var replyToCommentItems = [Comment]()
let repliesID = "repliesToCommentsID"
var numberOfRepliesToComment: Int = 0
fileprivate var oldConstraints = [NSLayoutConstraint]()
fileprivate var oldReplyTableHeightConstraints = [NSLayoutConstraint]()
fileprivate var totalCellHeight: CGFloat?

/** init is called before  dataObject.didSet*/
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    print("CommentTableViewCell.INIT")
    self.selectionStyle = .none
    setupViews()
}


var dataObject: Comment?{
    didSet{
        if let data = dataObject{
            guard
                let image = data.imageOfCommentor,
                let name = data.name,
                let comment = data.comment,
                let replies = data.repliesToComment else{return}
            print("dataObject.didSet for :\(name)")
            repliesTableView.sourceData = replies
            repliesTableView.reloadData()

            numberOfRepliesToComment = replies.count
            numRepliesLabel.text = "\(replies.count)"
            imgView.image = image
            nameLabel.text = name
            commentLabel.label.text = comment

            /**Only show number of replies to comments if they exist*/
            if numberOfRepliesToComment == 0{
                numRepliesLabel.alpha = 0
                repliesTextLabel.alpha = 0
            }
        }
    }
}


override func updateConstraints() {
    print("updateConstraints for : \(nameLabel.text!)")



    super.updateConstraints()
}

override func layoutSubviews() {
    super.layoutSubviews()
    print("layoutSubviews for \(nameLabel.text!)")

}


required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}


let borderSpace: CGFloat = 10
let viewSpace: CGFloat = 5

private func setupViews(){
    let c = contentView.safeAreaLayoutGuide

    /**Create commentLabel*/
    let padding = UIEdgeInsets.init(top: 3, left: 5, bottom: 3, right: 5)
    commentLabel = LabelWithPadding.init(frame: .zero, with: padding)
    commentLabel.translatesAutoresizingMaskIntoConstraints = false

    /**Create reply to comments tableView*/
    repliesTableView = RepliesToCommentsTableView.init(frame: .zero, style: .plain, sourceData: replyToCommentItems, cellid: repliesID)
    repliesTableView.translatesAutoresizingMaskIntoConstraints = false
    repliesTableView.isScrollEnabled = false
    repliesTableView.backgroundColor = UIColor.green

    timeReplyContainer.addSubview(timeAgoLabel)
    timeReplyContainer.addSubview(timeTextLabel)
    timeReplyContainer.addSubview(replyLabel)
    timeReplyContainer.addSubview(numRepliesLabel)
    timeReplyContainer.addSubview(repliesTextLabel)

    contentView.addSubview(imgView)
    contentView.addSubview(nameLabel)
    contentView.addSubview(commentLabel)
    contentView.addSubview(timeReplyContainer)
    contentView.addSubview(repliesTableView)

    commentLabel.label.font = UIFont.systemFont(ofSize: 12)
    commentLabel.label.numberOfLines = 0
    commentLabel.label.lineBreakMode = .byWordWrapping
    commentLabel.layer.cornerRadius = 7
    commentLabel.layer.masksToBounds = true
    commentLabel.backgroundColor = UIColor.appGrayExtraLightGray


    /**Layout constraints*/
    NSLayoutConstraint.deactivate(oldConstraints)
    NSLayoutConstraint.deactivate(oldReplyTableHeightConstraints)

    let newConstraints = [
        imgView.topAnchor.constraint(equalTo: c.topAnchor, constant: borderSpace),
        imgView.leadingAnchor.constraint(equalTo: c.leadingAnchor, constant: borderSpace),
        imgView.widthAnchor.constraint(equalTo: c.widthAnchor, multiplier: 0.08),
        imgView.heightAnchor.constraint(equalTo: c.widthAnchor, multiplier: 0.08),

        nameLabel.topAnchor.constraint(equalTo: c.topAnchor, constant: borderSpace),
        nameLabel.leadingAnchor.constraint(equalTo: imgView.trailingAnchor, constant: 10),
        nameLabel.trailingAnchor.constraint(equalTo: c.trailingAnchor, constant: -borderSpace),


        commentLabel.topAnchor.constraint(equalTo: nameLabel.bottomAnchor, constant: viewSpace),
        commentLabel.widthAnchor.constraint(equalTo: nameLabel.widthAnchor),
        commentLabel.trailingAnchor.constraint(equalTo: c.trailingAnchor, constant: -borderSpace),

        timeReplyContainer.topAnchor.constraint(equalTo: commentLabel.bottomAnchor, constant: borderSpace),
        timeReplyContainer.heightAnchor.constraint(equalToConstant: 30),
        timeReplyContainer.widthAnchor.constraint(equalTo: nameLabel.widthAnchor),
        timeReplyContainer.trailingAnchor.constraint(equalTo: c.trailingAnchor, constant: -borderSpace),
        timeReplyContainer.bottomAnchor.constraint(equalTo: repliesTableView.topAnchor, constant: -10),

        timeAgoLabel.leadingAnchor.constraint(equalTo: timeReplyContainer.leadingAnchor, constant: 5),
        timeAgoLabel.topAnchor.constraint(equalTo: timeReplyContainer.topAnchor),
        timeAgoLabel.trailingAnchor.constraint(equalTo: timeTextLabel.leadingAnchor, constant: -5),
        timeAgoLabel.topAnchor.constraint(equalTo: timeTextLabel.topAnchor),

        timeTextLabel.topAnchor.constraint(equalTo: timeReplyContainer.topAnchor),
        timeTextLabel.trailingAnchor.constraint(equalTo: replyLabel.leadingAnchor, constant: -10),
        replyLabel.topAnchor.constraint(equalTo: timeReplyContainer.topAnchor),

        numRepliesLabel.topAnchor.constraint(equalTo: timeReplyContainer.topAnchor),
        numRepliesLabel.trailingAnchor.constraint(equalTo: repliesTextLabel.leadingAnchor, constant: -5),
        repliesTextLabel.topAnchor.constraint(equalTo: timeReplyContainer.topAnchor),
        repliesTextLabel.trailingAnchor.constraint(equalTo: timeReplyContainer.trailingAnchor),

        repliesTableView.widthAnchor.constraint(equalTo: nameLabel.widthAnchor),
        repliesTableView.trailingAnchor.constraint(equalTo: c.trailingAnchor, constant: -borderSpace),
        repliesTableView.bottomAnchor.constraint(equalTo: c.bottomAnchor, constant: -borderSpace)]


    NSLayoutConstraint.activate([repliesTableView.heightAnchor.constraint(equalToConstant: 0)])
    NSLayoutConstraint.activate(oldReplyTableHeightConstraints)
    NSLayoutConstraint.activate(newConstraints)
    oldConstraints = newConstraints
    oldReplyTableHeightConstraints = [repliesTableView.heightAnchor.constraint(equalToConstant: 0)]

    setupTapGestures()
}

private func setupTapGestures(){
    let tapGesture = UITapGestureRecognizer.init(target: self, action: #selector(showRepliesToComment))
    self.repliesTextLabel.isUserInteractionEnabled = true
    self.repliesTextLabel.addGestureRecognizer(tapGesture)
}

@objc func showRepliesToComment(){
    print("show replies to comments")

    self.oldReplyTableHeightConstraints[0].isActive = false
    NSLayoutConstraint.deactivate(oldReplyTableHeightConstraints)

self.oldReplyTableHeightConstraints.remove (at: 0) print ("showRepliesToComment.oldReplyTableHeightConstraints: (oldReplyTableHeightConstraTimeRestRoTementTementTenceTech)") count: (oldReplyTableHeightConstraints.count) ")

    let newConstraints = [self.repliesTableView.heightAnchor.constraint(equalToConstant: 1000)]
    NSLayoutConstraint.activate(newConstraints)
    self.oldReplyTableHeightConstraints = newConstraints
    self.layoutIfNeeded()
}
}

КОНСОЛЬ показывает:

show replies to comments
showRepliesToComment.oldReplyTableHeightConstraints: []
showRepliesToComment.oldReplyTableHeightConstraints.count: 0
2020-02-05 09:04:36.468617+0000 Labuuk[8200:354387] [LayoutConstraints] Unable to 
simultaneously satisfy constraints.
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:0x600000425450 Labuuk.RepliesToCommentsTableView:0x7fdb13111000.height 
== 0   (active)>",
"<NSLayoutConstraint:0x60000041cb40 Labuuk.RepliesToCommentsTableView:0x7fdb13111000.height 
== 1000   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x60000041cb40 Labuuk.RepliesToCommentsTableView:0x7fdb13111000.height 
== 1000   (active)>

Как видно из консоли, я явно деактивировал, затем вручную удалил ограничение ( из отчаяния), а затем деактивировал ограничение высоты (для хорошей меры), и он все еще существует, чтобы вызвать конфликт!

Ответы [ 2 ]

0 голосов
/ 05 февраля 2020

Похоже, вы создаете два ограничения нулевой высоты в вашем setupViews методе:

private func setupViews(){
    [...]

    NSLayoutConstraint.activate([repliesTableView.heightAnchor.constraint(equalToConstant: 0)])
    [...]
    oldReplyTableHeightConstraints = [repliesTableView.heightAnchor.constraint(equalToConstant: 0)]

    setupTapGestures()
}

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

Попробуйте создать только одно ограничение, активировать его и установить oldReplyTableHeightConstraints чтобы узнать, исправит ли это:

private func setupViews(){
    [...]

    let zeroHeightTableViewConstraint = repliesTableView.heightAnchor.constraint(equalToConstant: 0)
    zeroHeightTableViewConstraint.isActive = true
    [...]
    oldReplyTableHeightConstraints = [zeroHeightTableViewConstraint]

    setupTapGestures()
}
0 голосов
/ 05 февраля 2020

Полагаю, проблема в том, что вы деактивируете список ограничений после его очистки.

Поэтому попробуйте заменить эту строку поверх метода showRepliesToComment :

NSLayoutConstraint.deactivate(oldReplyTableHeightConstraints)

Поскольку теперь вы пытаетесь деактивировать пустой список.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...