MQoder MQoder - 7 months ago 318
Swift Question

How to calculate height of nsattributed string with line spacing dynamically

im trying to calculate the height of a UILabel with LineSpacing attribute. The weird thing is that calculated value of the height of the normal label.text is lower then the label.attributedText with its lineheight. it looks like i'm doing something wrong, but cant find what, so please help :D.

The provided code is specially made for SO to make it compact and clear, it is implemented differently in my project.

extension NSAttributedString {
func heightWithWidth(width: CGFloat) -> CGFloat {
let maxSize = CGSize(width: width, height: CGFloat.max)

let boundingBox = self.boundingRectWithSize(maxSize, options: [.UsesLineFragmentOrigin, .UsesFontLeading, .UsesDeviceMetrics], context: nil)

return boundingBox.height
}
}

extension UILabel {

func getHeightWidthGivenWidthAndLineHeight(lineHeight: CGFloat, labelWidth: CGFloat) -> CGFloat {
let text = self.text
if let text = text {
let attributeString = NSMutableAttributedString(string: text)
let style = NSMutableParagraphStyle()

style.lineSpacing = lineHeight
attributeString.addAttribute(NSParagraphStyleAttributeName, value: style, range: NSMakeRange(0, text.characters.count))
let height = attributeString.heightWithWidth(labelWidth)
self.attributedText = attributeString
return height
}
return 0
}


I call this by

let contentHeight = contentLabel.text! == "" ? 0 : contentLabel.getHeightWidthGivenWidthAndLineHeight(3, labelWidth: labelWidth)


Working with normal strings (without spacing) works perfectly, when i use attributedstring with lineSpacing if fails te calculate the correct value.

Answer

You can just use UILabel's sizeThatFits. For example:

    let text = "This is\nSome\nGreat\nText"

    let contentHeight = contentLabel.text! == "" ? 0 : contentLabel.getHeightWidthGivenWidthAndLineHeight(6, labelWidth: labelWidth) 
    //returns 73.2

But just setting

    contentLabel.attributedText = contentLabel.attributedString //attributedString is same as getHeightWidthGivenWidthAndLineHeight

    let size = contentLabel.sizeThatFits(contentLabel.frame.size) 
    //returns (w 49.5,h 99.5)

Code for attributedString added to your extension, if you need to see that:

var attributedString:NSAttributedString?{
        if let text = self.text{
            let attributeString = NSMutableAttributedString(string: text)
            let style = NSMutableParagraphStyle()

            style.lineSpacing = 6
            attributeString.addAttribute(NSParagraphStyleAttributeName, value: style, range: NSMakeRange(0, text.characters.count))
            return attributeString
        }
        return nil
    }