-1

I have added programmatically some constraints in the views I have inside of a custom UICollectionViewCell, but I've noticed that when a cell is being reused, the constraints are probably being re-added.

This is what’s being logged:

> Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints
> to catch this in the debugger. The methods in the
> UIConstraintBasedLayoutDebugging category on UIView listed in
> <UIKitCore/UIView.h> may also be helpful. 2020-07-21
> 01:00:10.466637+0300 AutoLayout Message Cells[5227:336361]
> [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:0x600000435090 AutoLayout_Message_Cells.MessageCollectionViewCell:0x7fbd76e24670.height
> == UIView:0x7fbd76e291b0.height   (active)>",
>     "<NSLayoutConstraint:0x6000004350e0 V:|-(8)-[UILabel:0x7fbd76e29510'UOA']   (active, names:
> '|':UIView:0x7fbd76e291b0 )>",
>     "<NSLayoutConstraint:0x6000004351d0 UILabel:0x7fbd76e29510'UOA'.height == 30   (active)>",
>     "<NSLayoutConstraint:0x600000435220 V:[UILabel:0x7fbd76e29510'UOA']-(-12)-[UILabel:0x7fbd76e29790'2h']  
> (active)>",
>     "<NSLayoutConstraint:0x600000435310 UILabel:0x7fbd76e29790'2h'.height == 30   (active)>",
>     "<NSLayoutConstraint:0x6000004353b0 V:[UILabel:0x7fbd76e29790'2h']-(16)-[UITextView:0x7fbd7805b200'Lorem
> ipsum dolor sit ame...']   (active)>",
>     "<NSLayoutConstraint:0x600000435400 UITextView:0x7fbd7805b200'Lorem ipsum dolor sit ame...'.bottom ==
> UIView:0x7fbd76e291b0.bottom - 1   (active)>",
>     "<NSLayoutConstraint:0x60000042a990 'UIView-Encapsulated-Layout-Height'
> AutoLayout_Message_Cells.MessageCollectionViewCell:0x7fbd76e24670.height
> == 50   (active)>" )

And here's my cell's code:

import UIKit

class MessageCollectionViewCell: UICollectionViewCell {
    @IBOutlet var textView: UITextView!
    @IBOutlet var schoolLabel: UILabel!
    @IBOutlet var dateLabel: UILabel!
    
    override func awakeFromNib() {
        super.awakeFromNib()
        setupConstraints()
    }
    
    fileprivate func setupConstraints() {
        setupCellConstraints()
        setupSchoolLabelConstraints()
        setupDateLabelConstraints()
        setupTextViewConstraints()
    }
    
    fileprivate func setupCellConstraints() {
        self.contentView.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            self.contentView.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width - (self.frame.origin.x * 2))
        ])
        
        NSLayoutConstraint.activate([
            self.widthAnchor.constraint(equalTo: self.contentView.widthAnchor),
            self.heightAnchor.constraint(equalTo: self.contentView.heightAnchor)
        ])
    }
    
    fileprivate func setupSchoolLabelConstraints() {
        schoolLabel.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            schoolLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 8),
            schoolLabel.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 8),
            schoolLabel.trailingAnchor.constraint(equalTo: self.contentView.centerXAnchor, constant: 60),
            schoolLabel.heightAnchor.constraint(equalToConstant: 30)
        ])
    }
    
    fileprivate func setupDateLabelConstraints() {
        dateLabel.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            dateLabel.topAnchor.constraint(equalTo: schoolLabel.bottomAnchor, constant: -12),
            dateLabel.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 8),
            dateLabel.trailingAnchor.constraint(equalTo: self.contentView.centerXAnchor, constant: 60),
            dateLabel.heightAnchor.constraint(equalToConstant: 30)
        ])
    }
    
    fileprivate func setupTextViewConstraints() {
        textView.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            textView.topAnchor.constraint(equalTo: dateLabel.bottomAnchor, constant: 16),
            textView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -1),
            textView.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 8),
            textView.trailingAnchor.constraint(lessThanOrEqualTo: self.contentView.centerXAnchor, constant: 60)
        ])
    }

Is there a way to clear all constraints before re-adding them?

7
  • It's the only way to go? I don't think keeping references to the constraints is the best... Commented Jul 20, 2020 at 22:25
  • OK I just looked at your constraints and they are wrong in and of themselves. Commented Jul 20, 2020 at 22:39
  • I'm just starting using AutoLayout so you're probably right! What have I done wrong? Commented Jul 20, 2020 at 22:44
  • Just configure the constraints in the storyboard. And do not constrain the cell or the content view. Delete all that code. Commented Jul 20, 2020 at 22:49
  • I'm constraining the cell's width so it can have a dynamic height depending on the textViews text Commented Jul 20, 2020 at 22:51

1 Answer 1

0

I too use the constraints programmatically instead of in the storyboard. The problem you have is that some contraints can't coexist.

For exemple in the code I don't see this:

>     "<NSLayoutConstraint:0x60000042a990 'UIView-Encapsulated-Layout-Height'
> AutoLayout_Message_Cells.MessageCollectionViewCell:0x7fbd76e24670.height
> == 50   (active)>" )

Somewhere (maybe in the storyboard?) you are giving an heigth of 50, but:

the cell has the same height of the contentView:

self.heightAnchor.constraint(equalTo: self.contentView.heightAnchor)

in the cell you are giving:

        schoolLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 8),
....
        schoolLabel.heightAnchor.constraint(equalToConstant: 30)

so we have 8 form the top of the content + 30 of height (38), then:

        dateLabel.topAnchor.constraint(equalTo: schoolLabel.bottomAnchor, constant: -12),
....
        dateLabel.heightAnchor.constraint(equalToConstant: 30)

you return up of 12 and then again a height of 30 (38 - 12 + 30 = 56). We are out of the 50 fo the cell, plus you add the text:

        textView.topAnchor.constraint(equalTo: dateLabel.bottomAnchor, constant: 16),
        textView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -1)

whose heigth will result negative (the textView top is at 56 + 16 = 72, but it's bottom is at 50 (the constraint we don't see) - 1 = 49 --> it's hieght is -23

Sign up to request clarification or add additional context in comments.

2 Comments

So what should I do? I checked and I don’t specify a height of 50 for the cell anywhere in the project
I should remove the height from the lables and run it, checking what happens. The message say 'AutoLayout_Message_Cells', so it can be something odd.. like you decided to have X row in the view and to create them it create the constraint of 50 heigth. Or you can specify an height of 80 (or 72 to be precise) for the content view and see if the error comes again.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.