3

I use visual format to layout subviews in cell like this:

contentView.addSubview(accountLabel)
contentView.addSubview(contentLabel)
contentView.addSubview(timeLabel)

let views: [String : Any] = [
    "accountLabel": accountLabel,
    "contentLabel": contentLabel,
    "timeLabel": timeLabel
]

let hConstraint1 = NSLayoutConstraint.constraints(withVisualFormat: "H:|-15-[accountLabel]-[timeLabel]-8-|", options: [.alignAllCenterY], metrics: nil, views: views)
let hConstraint2 = NSLayoutConstraint.constraints(withVisualFormat: "H:[contentLabel]-8-|", options: [], metrics: nil, views: views)
let vConstraint = NSLayoutConstraint.constraints(withVisualFormat: "V:|-12-[accountLabel]-8-[contentLabel]-12-|", options: [.alignAllLeading], metrics: nil, views: views)
NSLayoutConstraint.activate(hConstraint1+hConstraint2+vConstraint)

And it looks ok when run in simulator:

enter image description here

However, some layout issues occur when debugging view hierarchy:

enter image description here

Why these layout issues occur while the runtime UI looks ok?

Is something wrong with the visual format string above? Or it's the bug of Xcode?

How to remove these layout issues?

a_tuo
  • 651
  • 7
  • 23
  • Are you using storyboard ? – 3stud1ant3 Aug 18 '17 at 10:46
  • @user1000 The controller and tableView is created in storyboard. The cell is created by code. – a_tuo Aug 18 '17 at 11:06
  • Are you using `tableView.rowHeight = UITableViewAutomaticDimension`? By the way - please don't post screen-caps of your code... post the code itself (that way, if someone wants to try and replicate your condition, we can copy/paste it). – DonMag Aug 18 '17 at 13:39
  • @DonMag Yeah, I use `UITableViewAutomaticDimension`. What's the problem? By the way, thanks for your advice. – a_tuo Aug 18 '17 at 23:27
  • @DonMag I have updated my question with the code. – a_tuo Aug 19 '17 at 00:18

1 Answers1

10

Well, I'm not an expert with constraints, but I do see one "correctable" issue and one "that's just weird maybe it's a bug" issue.

As I understand it, auto-layout will try to satisfy the constraints -- even if they are ambiguous. If it fails, then you see the error message in the console, usually along the lines of "will attempt to satisfy by breaking..."

So the warning information you see in Debug View Hierarchy is more informational than "fix this error" directive.

That said...


You have accountLabel and timeLabel constrained relative to each other, but they both have the same Compression Resistance. So, as long as the amount of text in each label would "fit", all is OK.

But suppose the accountLabel gets a text string of "This user name is too long to fit here"?

Should it look like this (I use background colors to help see the frames):

enter image description here

or like this:

enter image description here

That's why the horizontal position and width is showing as "ambiguous".

You can fix that issue by adding one line. Assuming you want accountLabel to be truncated:

    accountLabel.setContentCompressionResistancePriority(749, for: .horizontal)

will do the trick. The default is 750, so that line tells auto-layout to give timeLabel the higher Resistance.


The Height and Vertical positions showing as ambiguous don't seem right. I don't see anything wrong with the constraints.

If I use the same font for all three labels? No ambiguous warnings.

If I use a different font size for the timeLabel (as you show in your images), now there are warnings in debug view hierarchy.

Except... If I scroll so the cells are reused? The warnings have gone away!

EDIT: As the OP states in his comment, the Vertical ambiguity can be eliminated (prior to scrolling) by giving different Content Hugging Priority values to accountLabel and contentLabel.

Since the default Hugging priority is 250:

    accountLabel.setContentHuggingPriority(249, for: .vertical)

Clears that warning.

I'm not convinced it's necessary... but it does appear to do the job.

DonMag
  • 69,424
  • 5
  • 50
  • 86
  • @DonMag Follow your thought, I change the vertical `contentHuggingPriority` of `contentLabel` to be higher than the default value 250. Then, the warnings go away! Actually, when the vertical `contentHuggingPriority` of the `contentLabel` and `accountLable` is different, the warnings will go away. You may update your answer and I'll accept it. – a_tuo Aug 20 '17 at 05:35
  • @a_tuo - I sure thought I gave that a try... but obviously not, as it does the job. I updated my answer. – DonMag Aug 20 '17 at 15:22