NSAttributedString boundingRect返回错误的高度 [英] NSAttributedString boundingRect returns wrong height

查看:473
本文介绍了NSAttributedString boundingRect返回错误的高度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我这样计算NSAttributedString的高度.

let maxSize = NSSize(width: w, height: CGFloat.greatestFiniteMagnitude)
let rect = boundingRect(with: maxSize, options: [.usesFontLeading, .usesLineFragmentOrigin])
let height = rect.integral.size.height

我尝试了SO上提到的每个"hack",但是宽度越小,字符串高度变得越不准确(计算出的高度大于实际高度).

I tried about every "hack" that was mentioned on SO, yet the string height gets more inaccurate the smaller the width gets (the calculated height is larger than the actual height).

根据其他帖子,以下内容会导致尺寸计算出现问题:

According to other posts the following things cause problems with size calculation:

  • 空白
  • 没有前景色
  • 没有背景色
  • 低于300的宽度无效(?)

我发现这些建议都没有任何不同.属性字符串是行的串联,每行都有一个foregroundColorbackgroundColor.该字符串还具有以下段落样式.

I have found that none of these suggestions make any difference. The attributed string is a concatenation of lines, each having a foregroundColor and backgroundColor. The string also has the following paragraph style.

 let pstyle = NSMutableParagraphStyle()
 pstyle.lineSpacing = 6
 pstyle.lineBreakMode = .byWordWrapping

和大小为11的userFixedPitchFont.

宽度越小,为什么高度误差会变大?

Why does the height error get larger the smaller the width is?

PS:我想这与lineBreak有关,因为如果用更多的行换行,错误会变得更大.

PS: I imagine it has something to do with lineBreak since the error gets larger if more lines are word wrapped.

推荐答案

我发现此解决方案有效.请注意,如果您未将lineFragmentPadding设置为0,则会产生与boundingRect相同(错误)的结果.

I found that this solution works. Note that if you don't set the lineFragmentPadding to 0, it produces the same (wrong) results as boundingRect.

extension NSAttributedString {

    func sizeFittingWidth(_ w: CGFloat) -> CGSize {
        let textStorage = NSTextStorage(attributedString: self)
        let size = CGSize(width: w, height: CGFloat.greatestFiniteMagnitude)
        let boundingRect = CGRect(origin: .zero, size: size)

        let textContainer = NSTextContainer(size: size)
        textContainer.lineFragmentPadding = 0

        let layoutManager = NSLayoutManager()
        layoutManager.addTextContainer(textContainer)

        textStorage.addLayoutManager(layoutManager)

        layoutManager.glyphRange(forBoundingRect: boundingRect, in: textContainer)

        let rect = layoutManager.usedRect(for: textContainer)

        return rect.integral.size
    }
}

这篇关于NSAttributedString boundingRect返回错误的高度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆