1

I'm trying to get a minimum cell height for a tableView cell. This works, but it throws a zillion of warnings into the debugger console of Xcode.

Question 1: Why?

Question 2: How to get rid of these warnings while implementing a minimum cell height?

2018-11-16 19:18:13.080131+0100 Test[46195:5492055] [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:0x600003a91450 V:[UILabel:0x7fa4f2e05470'One ']-(0)-|   (active, names: '|':UITableViewCellContentView:0x7fa4f2e17f70 )>",
    "<NSLayoutConstraint:0x600003a91310 V:|-(0)-[UILabel:0x7fa4f2e05470'One ']   (active, names: '|':UITableViewCellContentView:0x7fa4f2e17f70 )>",
    "<NSLayoutConstraint:0x600003a911d0 UILabel:0x7fa4f2e05470'One '.height >= 44   (active)>",
    "<NSLayoutConstraint:0x600003a8dbd0 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7fa4f2e17f70.height == 44   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x600003a911d0 UILabel:0x7fa4f2e05470'One '.height >= 44   (active)>

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.
2018-11-16 19:18:13.081005+0100 Test[46195:5492055] [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:0x600003a953b0 V:[UILabel:0x7fa4f2c018d0'Three ']-(0)-|   (active, names: '|':UITableViewCellContentView:0x7fa4f2c06510 )>",
    "<NSLayoutConstraint:0x600003a95450 V:|-(0)-[UILabel:0x7fa4f2c018d0'Three ']   (active, names: '|':UITableViewCellContentView:0x7fa4f2c06510 )>",
    "<NSLayoutConstraint:0x600003a94be0 UILabel:0x7fa4f2c018d0'Three '.height >= 44   (active)>",
    "<NSLayoutConstraint:0x600003a95cc0 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7fa4f2c06510.height == 44   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x600003a94be0 UILabel:0x7fa4f2c018d0'Three '.height >= 44   (active)>

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.

This can be simply reproduced with this very simple setup:

enter image description here

enter image description here

  • New UITableView with controller MyTableView
  • 1 prototype cell with class MyTableViewCell
  • Cell has 1 label linked to MyTableViewCell.label

I have the following constrains for the label:

enter image description here

This is to make sure I have a minimum cell height of 44.

The view controller:

import UIKit

class MyTableViewController: UITableViewController {
    let data: [String] = [
    "One ",
    "Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two Two ",
    "Three "
    ]

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.estimatedRowHeight = 44.0
        tableView.rowHeight = UITableView.automaticDimension

    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) as! MyTableViewCell

        cell.label.text = data[indexPath.row]

        return cell
    }

}

The cell:

import UIKit

class MyTableViewCell: UITableViewCell {
    @IBOutlet weak var label: UILabel!
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • Hi, Arjen! You use custom or basic style for cell? – Peter Tretyakov Nov 16 '18 at 18:38
  • Hi Peter. Custom. With my own class `MyTableViewCell`. See above. I also tried to add a 2nd view to the cell and specify the minimum on that view. But as soon as it works, I get those warnings. – Arjen Hiemstra Nov 16 '18 at 18:48
  • The only solution that seems to work is this one: [link](https://stackoverflow.com/a/48853081/6854314). But it seems to be overkill to me. It looks like a possible bug in the constraints engine. – Arjen Hiemstra Nov 16 '18 at 18:57
  • Especially, because this also happens for static cells. To create a class for each static prototype cell would be insane. – Arjen Hiemstra Nov 16 '18 at 19:10
  • Curious... I'm not getting the "broken constraint" warnings. I'm using `Xcode 9 / Swift 4.1` and running on `iOS 11.3`. If you set `.estimatedRowHeight = 50.0` do you still get the warnings? If you run on an `11.3` simulator do you still get the warnings? – DonMag Nov 16 '18 at 19:16

2 Answers2

2

The solution of Peter Tretyakov works.

Another solution I found was here.

Against your intuition, you need to lower the priority of your >= constraint with 1 from 1000 to 999. Then everything works as expected without warnings.

1

The problem is with height >= 44 constraint of UILabel in cell. This happening because UITableView automatically added height = 44 constraint to cell contentView. Only to cell with One and Three labels because for Two... label it uses label's size to calculate row height.

But cell's contentView includes not only your label but a separator with default height 0.5, so your label in default cell's height will be not 44 but 43.5 and that's why your constraints break.

So you need to make label's height constraint >= 43.5 and warnings will disappear.

Peter Tretyakov
  • 3,380
  • 6
  • 38
  • 54