I have a single-line UILabel with the following configuration:
let label = UILabel()
label.text = "Lorem ipsum dolor sit amet"
label.numberOfLines = 1
When I call sizeThatFits(size)
on this label with a small size width, the result is always a size with a bigger width.
let labelSize = label.sizeThatFits(CGSize(width: 30, height: UILabel.noIntrinsicMetric))
// labelSize.width > 30
Shouldn't sizeThatFits()
return a size that is smaller or equal than the fitting size?
Neither of the suggested answers clarify this question.
Calling textRect(forBounds:limitedToNumberOfLines:)
returns a zero width and systemLayoutSizeFitting()
returns the same size as sizeThatFits()
. There is no other workaround that can be used in any of the suggested answers.
The documentation says:
The intrinsic content size for a label defaults to the size that displays the entirety of the content on a single line.
The whole point of sizeThatFits(_:)
is “tell me what size I need to show all of this text.” The width parameter is essentially ignored if numberOfLines
is 1
.
The width supplied to sizeThatFits(_:)
only comes into play when using numberOfLines
of 0
(or greater than 1
). In that scenario, sizeThatFits(_:)
will now let us know the label’s height (and width) that will fit the text wrapped within the originally supplied width.
I understand from your comments that you were expecting it to never return a value whose width that exceeded 30
even if numberOfLines
is 1
. Right or wrong, that simply is not how it works. If you want to clamp the width to not exceed 30
, you would do this yourself:
let label = UILabel()
label.text = "Lorem ipsum dolor sit amet"
label.numberOfLines = 1
var size = label.sizeThatFits(CGSize(width: 30, height: UILabel.noIntrinsicMetric))
size.width = min(size.width, 30)