14

I am a beginner in Swift and I am trying to get the height of a label. The label has multiple lines of text. I want to know the total height it occupies on the screen.

vb11
  • 203
  • 1
  • 2
  • 9

5 Answers5

18

Swift 4 with extension

extension UILabel{

public var requiredHeight: CGFloat {
    let label = UILabel(frame: CGRect(x: 0, y: 0, width: frame.width, height: CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    label.text = text
    label.attributedText = attributedText
    label.sizeToFit()
    return label.frame.height
  }
}
levin varghese
  • 660
  • 11
  • 12
15

it's simple, just call

label.bounds.size.height
Ahmed R.
  • 1,093
  • 1
  • 11
  • 22
  • I am printing the size on console and getting 0.0 for my label's height. This is what I tried : print(label.bounds.size.height) – vb11 Apr 08 '16 at 20:47
  • How is your label set up? If you are using Auto Layout, you will need to create constraints to give the label a height. – Slayter Apr 08 '16 at 20:49
  • 1
    I have a vertical stack view and have 3 labels in it. Yes I am using auto layout. But is it not possible to get the default height that the label takes without setting it manually? @Slayter – vb11 Apr 08 '16 at 20:59
  • The default height would be 0 until you give it some constraints. – Slayter Apr 08 '16 at 21:04
  • Note that the height might not be set yet if you print it in the initializer or e.g. in `viewDidLoad()`. Instead you should print the height in `viewWillAppear()`. – tonisuter Apr 08 '16 at 21:16
  • @AhmedR, bro could you please take a look at my question https://stackoverflow.com/questions/44966983/how-to-set-label-height-for-auto-adjust-in-read-more-less-with-swift-3 ? – May Phyu Jul 07 '17 at 09:37
  • try this Label.frame.height – Giang Nov 07 '18 at 09:55
10

Updated for Swift 3

func estimatedHeightOfLabel(text: String) -> CGFloat {

    let size = CGSize(width: view.frame.width - 16, height: 1000)

    let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)

    let attributes = [NSFontAttributeName: UIFont.systemFont(ofSize: 10)]

    let rectangleHeight = String(text).boundingRect(with: size, options: options, attributes: attributes, context: nil).height

    return rectangleHeight
}

override func viewDidLoad() {
    super.viewDidLoad()

    guard let labelText = label1.text else { return }
    let height = estimatedHeightOfLabel(text: labelText)
    print(height)
}

enter image description here

iAj
  • 3,467
  • 1
  • 28
  • 33
  • if you want to use this method for layouting, make sure to return ceil(rectangleHeight), otherwise autolayout might crop off text – productioncoder Aug 20 '17 at 22:23
  • @slashburn can you plz elaborate more what will be the actual problem when we not used return ceil(rectangleHeight)? – iAj Aug 24 '17 at 07:09
  • 1
    The overall approach works perfectly. When I tried the code on a UILabel with a longer text, the text got cropped off. Therefore I've used ceil() to get the next biggest integer number and then the content was no longer cropped off. – productioncoder Aug 24 '17 at 15:32
  • @slashburn what do you mean by when using this method for layout make sure to cast the rectHeight as ceil because the text got cropped off? I don't understand how the text got cropped off. I'm using this inside a cell's sizeForItem and sizeForHeader. The textLabel inside the cell sometimes wraps to 2-3 lines and other times it's 1 line only with no wrapping (maybe 2 -3 words instead of a sentence). Both of those get called before the cell is displayed, do I need to use return ceil(rectangleHeight)? – Lance Samaria Jul 24 '18 at 19:59
  • In my experiments I found that if you specify something like 95.46875 as a height then sometimes auto layout had trouble fitting the text in correctly. Therefore I just round up the number. So 95.46875 gets rounded up to 96 and so I can be sure that there is no pixel issue and that the text will fit in. Don't know if that's the best approach but this worked for me – productioncoder Jul 25 '18 at 10:33
  • @slashburn I forgot to thank you for the reply and explanation. Thanks! :) – Lance Samaria Sep 14 '18 at 11:31
1

@iajmeri43's answer Updated for Swift 4

func estimatedLabelHeight(text: String, width: CGFloat, font: UIFont) -> CGFloat {

    let size = CGSize(width: width, height: 1000)

    let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)

    let attributes = [NSAttributedStringKey.font: font]

    let rectangleHeight = String(text).boundingRect(with: size, options: options, attributes: attributes, context: nil).height

    return rectangleHeight
}

To use it (step 4):

// 1. get the text from the label
guard let theLabelsText = myLabel.text else { return }

// 2. get the width of the view the label is in for example a cell
// Here I'm just stating that the cell is the same exact width of whatever the collection's width is which is usually based on the width of the view that collectionView is in
let widthOfCell = self.collectionView.frame.width

// 3. get the font that your using for the label. For this example the label's font is UIFont.systemFont(ofSize: 17)
let theLabelsFont = UIFont.systemFont(ofSize: 17)

// 4. Plug the 3 values from above into the function
let totalLabelHeight = estimatedLabelHeight(text: theLabelsText, width: widthOfCell, font: theLabelsFont)

// 5. Print out the label's height with decimal values eg. 95.46875
print(totalLabelHeight)

// 6. as @slashburn suggested in the comments, use the ceil() function to round out the totalLabelHeight
let ceilHeight = ceil(totalLabelHeight)

// 7. Print out the ceilHeight rounded off eg. 95.0
print(ceilHeight)
Lance Samaria
  • 11,429
  • 8
  • 67
  • 159
0

Swift 5 ioS 13.2 tested 100%, best solution when the UILabel numberOfLines = 0

Note, result is rounded. Just remove ceil() if you don't want it.

If you want to get height -> give storyboard width of UILabel

If you want to get width -> give storyboard height of UILabel

    let stringValue = ""//your label text
    let width:CGFloat = 0//storybord width of UILabel
    let height:CGFloat = 0//storyboard height of UILabel
    let font = UIFont(name: "HelveticaNeue-Bold", size: 18)//font type and size

    func getLableHeightRuntime() -> CGFloat {
        let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = stringValue.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
        return ceil(boundingBox.height)
    }

    func getLabelWidthRuntime() -> CGFloat {
        let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
        let boundingBox = stringValue.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
        return ceil(boundingBox.width)
    }
Malith Kuruwita
  • 244
  • 1
  • 5
  • 9