1

In SpriteKit, you can now set the number of lines of an SKLabelNode, so the label may go through a few lines.

let lb = SKLabelNode(fontNamed: "Courier-bold")
lb.numberOfLines = 0
lb.preferredMaxLayoutWidth = size.width

Is there any way to determine the ACTUAL number of lines the SKLabelNode is rendered to?

Tamás Sengel
  • 55,884
  • 29
  • 169
  • 223
Mike Keskinov
  • 11,614
  • 6
  • 59
  • 87

1 Answers1

2

You should calculate the number of lines by generating a UILabel with the same text formatting parameters and calculate its actual number of lines, described here.

With regular text:

let preferredMaxWidth: CGFloat = <maximum width of the label>

let label = UILabel()
label.text = lb.text
label.font = UIFont(name: lb.fontName, size: lb.fontSize)
label.numberOfLines = lb.numberOfLines

label.frame.size.width = preferredMaxWidth
label.sizeToFit()
label.frame.size.width = preferredMaxWidth

let numberOfLines = Int(label.frame.size.height / label.font.pointSize)

With attributed text (if it only uses one type of font):

let preferredMaxWidth: CGFloat = <maximum width of the label>

let label = UILabel()
label.attributedText = lb.attributedText
label.numberOfLines = lb.numberOfLines

label.frame.size.width = preferredMaxWidth
label.sizeToFit()
label.frame.size.width = preferredMaxWidth

guard let pointSize = (lb.attributedText.attributes(at: 0, effectiveRange: nil)[.font] as? UIFont)?.pointSize else {
    return
}

let numberOfLines = Int(label.frame.size.height / pointSize)
Tamás Sengel
  • 55,884
  • 29
  • 169
  • 223
  • 1
    The UILabel part of your answer is pointless, you can do everything you said without the need to create the UILabel – Knight0fDragon Feb 01 '18 at 17:43
  • @Knight0fDragon You are right, thank you, there were several misdirections in my answer. I edited them out. – Tamás Sengel Feb 01 '18 at 17:46
  • This answer needs more TLC, We need to factor in the type of line breaking. Also I do not think sizeThatFits is necessary, I believe that will end up getting you the size of the `SKLabel` anyway. Your attributed text seems to actually be the way to go (Does the `SKLabel` even render regular text? I always thought that when you edit text, it changes the attributed text and the `SKLabel` only renders attributed text, so you may actually get away with only having to worry about the 2nd clause) – Knight0fDragon Feb 01 '18 at 18:00
  • @Knight0fDragon If you only set the `text` property of an `SKLabelNode`, it will return `nil` for `attributedText`. – Tamás Sengel Feb 01 '18 at 18:05
  • OK, then it must be once you assign the attributedText with a value that this behavior happens – Knight0fDragon Feb 01 '18 at 18:08