2
votes

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?

1
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
@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.Will Clarke
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
@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.Will Clarke
Try cell.mainStackView.setNeedsLayout() cell.mainStackView.layoutIfNeeded() (mainStackView is an outlet) instead of cell.contentView.setNeedsLayout() cell.contentView.layoutIfNeeded(). Does it change anything?kamil3

1 Answers

0
votes

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.