2

I have two labels in a horizontal stack view. The labels have numberOfLines set to 0 so they will wrap infinitely, Vertical Content Compression Resistance set to 1000 so they will always be their full height, Horizontal Compression Resistance set to 250 because I want them to be able to be shrunk, and Content Hugging set to 1000 (both axes, because I always want the frame to hug the label). See:

Interface Builder screenshot

Then that stack view is the only item in a self-sizing cell. It's constrained to the top, bottom, leading, and trailing margins. The stack view has the same compression resistance/content hugging as the labels.

At runtime, in my cellForRowAt indexPath function, I set the two labels to text of varying length. And since I've read elsewhere that layout can be a problem here, I also do:

    cell.contentView.setNeedsLayout()
    cell.contentView.layoutIfNeeded()

However, when I run, I see some odd behavior initially. But when I scroll around, things start to look okay. It seems the problem has to do with cell reuse, but I can't figure out what's wrong.

Simulator Screen Shots

On the left - the initial load. Note, the value label is being cut off entirely, and in the second cell, the proportional spacing doesn't seem to be working at all - the value label is very narrow when compared to the name label.

On the right - the table once I've scrolled to the bottom of the list and back to the top. This is exactly what I expect: labels are spaced proportionally based on their intrinsic content size. But how can I get this behavior without having to scroll around?

William Key
  • 173
  • 12
  • How are you expecting the Label widths to be calculated? Because in the top example, the right-label is very narrow (the width of the word "No")... but in the lower example, the right label is wider than 50%... – DonMag Apr 11 '17 at 20:03
  • @DonMag - according to Apple's documentation on Stack views, when you choose the distribution property of fillProportionally, "Views are resized proportionally based on their intrinsic content size along the stack view’s axis." So what I expect is for the widths to be calculated based on the labels' intrinsic content size. This seems to work fine when cells are reused, but not when cells load for the first time. – William Key Apr 11 '17 at 20:11
  • sure... except, what is the intrinsic content size? For a single label, default font of 17, the *intrinsic content size* of your "Fruitcake" text by itself is `528 x 20.5` ... if you restrict the width - either by setting constraints on the label or by embedding it in a stack view that has a width constraint, then it will wrap to multiple lines (if needed), and the *intrinsic height* will change... but if you have two labels, which one's intrinsic height do you want to get the priority? – DonMag Apr 11 '17 at 20:21
  • @DonMag I mean, I don't know how UIStackView works under the hood. I'd imagine it just looks at the intrinsic content sizes of your text on a single line, given infinite width, and use the area of that content size to calculate the proportional width. But we really have no way of knowing, which is why I'm thinking I might submit a TSI to Apple and see if they can get a UIKit engineer to comment on it. – William Key Apr 11 '17 at 20:51
  • Try `cell.mainStackView.setNeedsLayout() cell.mainStackView.layoutIfNeeded()` (*mainStackView* is an outlet) instead of `cell.contentView.setNeedsLayout() cell.contentView.layoutIfNeeded()`. Does it change anything? – kamil3 Apr 13 '17 at 19:10

1 Answers1

0

I believe your biggest issue is with a Horizontal StackView, your width is dynamically calculated based on the content stacked. With your StackView limited to a specific width, based on your width constraints, the bigger job becomes how to calculate the width of the content. Then you're throwing in infinite lines which makes the dynamic width even more challenging because there has to be some threshold.

I would suggest having a defined width for either the FieldName or FieldValue, be it constants or relative widths based on percentages of the parent's width. I'm pretty sure your hugging and compression will just be fighting with one another because the FieldName can sometimes be longer than the FieldValue, and sometimes it's the opposite.

You have to set a hard limit somewhere.

kruskop
  • 11
  • 4
  • The frustrating thing is that it works great on cell reuse. The problems only come up when the cells are initially loaded from the storyboard. There must be some kind of under-the-hood magic that it does to calculate the right widths once it has loaded them the first time. I might submit a TSI to Apple to get a UIKit engineer to comment on this. – William Key Apr 11 '17 at 20:46
  • I honestly don't think there's any Apple issues. I think it's a matter of understanding how the API works. What I'm trying to tell you that you just stated is, there aren't any "right widths once it has loaded the first time". There is only, initial calculation and display, from here something has to tell the cell to draw correctly and non-uniform for custom widths. Whatever you are saying works "great" is a matter of pure circumstance due to the device type. – kruskop Apr 12 '17 at 13:12
  • In an attempt to be as explicit as possible: I'm telling you to set a "hard' limit for one of the content's widths because of the fact that both labels have the ability to run on into infinity. You're experiencing width problems because you expect magic that doesn't exist. – kruskop Apr 12 '17 at 13:14