NSAttributedString boundingRect returns 高度错误

NSAttributedString boundingRect returns wrong height

我这样计算一个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",但是宽度越小,字符串高度就越不准确(计算的高度大于实际高度)。

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

我发现 none 这些建议有任何不同。属性字符串是多行的串联,每行都有一个 foregroundColorbackgroundColor。字符串还有如下段落样式。

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

和尺寸为 11 的 userFixedPitchFont

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

PS:我想这与lineBreak有关,因为如果换行的行越多,错误就会越大。

我发现此解决方案有效。请注意,如果您不将 lineFragmentPadding 设置为 0,它会产生与 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
    }
}