Is there a cross-platform way of calculating the rendered NSSize of an NSAttributedString?

Here is a dedicated extension of such for macOS:

// MARK: - NSAttributedString extension

// Ref: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/TextLayout/Tasks/StringHeight.html

public extension NSAttributedString {
  @objc var boundingDimension: NSSize {
    let rectA = boundingRect(
      with: NSSize(width: Double.infinity, height: Double.infinity),
      options: [.usesLineFragmentOrigin]
    )
    let textStorage = NSTextStorage(attributedString: self)
    let textContainer = NSTextContainer()
    let layoutManager = NSLayoutManager()
    layoutManager.addTextContainer(textContainer)
    textStorage.addLayoutManager(layoutManager)
    textContainer.lineFragmentPadding = 0.0
    layoutManager.glyphRange(for: textContainer)
    let rectB = layoutManager.usedRect(for: textContainer)
    let width = ceil(max(rectA.width, rectB.width))
    let height = ceil(max(rectA.height, rectB.height))
    return .init(width: width, height: height)
  }
}

I just wonder whether this (thereotically) works on Linux and Windows.

I was under the impression that NSAttributedString doesn’t even exist on Windows. Either way, AppKit and SwiftUI definitely don’t, so I’m not sure what meaning the rendered size of a string would even have.

In the open source swift-foundation package, NSAttributedString does not exist but AttributedString does exist as a cross-platform stylized string type that is written natively in Swift. However, as @bbrk24 mentioned above, UI frameworks such as AppKit, UIKit, and SwiftUI are not currently built for non-Apple platforms such as Windows and Linux. This means that you won't be able to access APIs such as NSTextStorage or NSTextLayoutManager to find the size of the string. Since there isn't an Apple-provided UI framework on Windows/Linux, you'd likely want to calculate the size of your attributed string using whichever alternate mechanism you have decided to use for rendering the string on those platforms (if that rendering API provides some equivalent bounding size API)

3 Likes