0

I am trying to get the estimated size of the rectangle required to draw out a NSMutableAttributedString. The numbers that come not does not make any sense to me. I have a UIViewController with a UIlabel (txtField), with a UIlabel.numberOfLines = 3. I would like to estimate the height of this NSMutableAttributedString were i to set UIlabel.numberOfLines= 0.

With reference to the console reading, I do not understand why the estimated height of the rectangle required to draw the entire NSMutableAttributedString is less than that if it were constrained to just 3 lines?

var txtField: UILabel = {
    let label = UILabel()
    label.numberOfLines = 3
    label.translatesAutoresizingMaskIntoConstraints = false
    label.lineBreakMode = .byTruncatingTail
    return label
}()


override func viewDidLoad() {
    super.viewDidLoad()

    let content = "Pasture he invited mr company shyness. But when shot real her. Chamber her 
     observe visited removal six sending himself boy. At exquisite existence if an oh dependent excellent. Are gay head need down draw. Misery wonder enable mutual get set oppose the uneasy. End why melancholy estimating her had indulgence middletons. Say ferrars demands besides her address. Blind going you merit few fancy their. "

    let attributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14)]
    let attributedString = NSMutableAttributedString.init(string: content, attributes: attributes)

    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.lineSpacing = 1.5
    paragraphStyle.lineBreakMode = .byTruncatingTail
    attributedString.addAttributes([.paragraphStyle : paragraphStyle], range: NSRange(location: 0, length: attributedString.length))
    txtField.attributedText = attributedString

}


override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if let attText = txtField.attributedText{
        let size = CGSize.init(width: txtField.frame.width - 20, height: 1000)
        let estimatedFrame = attText.boundingRect(with: size, options: .usesLineFragmentOrigin, context: nil)
        print("txtField.frame: \(txtField.frame)")
        print("estimatedFrame: \(estimatedFrame)")

    }
}

CONSOLE:

txtField.frame: (0.0, 0.0, 394.0, 53.333333333333336)
estimatedFrame: (0.0, 0.0, 367.28125, 16.70703125)
johnDoe
  • 709
  • 11
  • 29

1 Answers1

2

This is wrong:

paragraphStyle.lineBreakMode = .byTruncatingTail

Attributed string line breaking is different from label line breaking. Your attributed string needs to have a line break mode that wraps. Otherwise you are measuring the height of just one line.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • ok. So I delete the line above. Then i find a NSAttributedString.Key relating to line break mode that wraps and add to attribute of NSMutableAttributedString? Please could you elborate with code becuase i can't seem to find the concerned NSAttributedString.Key – johnDoe Dec 15 '19 at 16:14
  • I didn’t say delete it. But I do think you might want to change the line break mode to something with “wrap” in its name. – matt Dec 15 '19 at 16:23
  • ok i've found paragraphStyle. lineBreakMode = .byWordWrapping. Thank you ! – johnDoe Dec 15 '19 at 16:24