How to split an `AttributedString` produced by `.number.precision(.fractionLength(2)).attributed` into the whole and fraction parts?

(Since AttributedString relies heavily on quite a few of Swift's features like dynamicMemberLookup, it's the most "Swifty" API I have seen. So I think this is appropriate for this forum.)

I need help figuring out this very basic operation on AttributedString:

let n = 1234567.898
let s = n.formatted(.number.precision(.fractionLength(2)).attributed)

s now is an AttributedString: 1,234,567.90

I need to break apart s into two AttributedString parts:

1,234,567. (<== includes the decimalSeparator)
90

I think it's just simply calling subscript<R>(bounds: R) -> AttributedSubstring?

But I can't figure out how to get the two index Range's. I know how to get the decimalSeparator run. But how to come up with the two index Range's?

I know how to get the decimalSeparator run.

If you can get this as a range then you can pass its upper bound to any prefix mechanism. For example:

let n = 1234567.898
let s = n.formatted(.number.precision(.fractionLength(2)).attributed)
let decimalRunQ = s.runs.first { e in
    guard case .decimalSeparator? = e.numberSymbol else { return false }
    return true
}
guard let decimalRun = decimalRunQ else { fatalError() }
let prefixAttributed = s[..<decimalRun.range.upperBound]
print(prefixAttributed)
// … elided …
let prefixPlain = String(s.characters[..<decimalRun.range.upperBound])
print(prefixPlain)
// 1,234,567.

Share and Enjoy

Quinn “The Eskimo!” @ DTS @ Apple

1 Like