I have set up a simple playground to demonstrate my problem in retrieving the attributes of attributed strings. Perhaps I do not understand how to define ranges: perhaps I am missing something else.
I have define a NSMutableAttributedString that has two colors in it as well as a change in font to bold(for the blue) and italic(for the red):
var someText = NSMutableAttributedString()
let blueAttri : [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 12), NSAttributedString.Key.foregroundColor : UIColor.blue]
let redAttri : [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: UIFont.italicSystemFont(ofSize: 12), NSAttributedString.Key.foregroundColor : UIColor.red]
someText = NSMutableAttributedString(string: "Some blue string here; ", attributes: blueAttri)
someText.append(NSMutableAttributedString(string: "Some red string here; ", attributes: redAttri))
At this point the string looks fine showing text with both colors.
I then have defined 3 ranges (attempting different approaches to defining ranges.)
var range1 = NSRange()
var range2 = NSRange(location: 0, length: someText.length)
var range3 = NSRange(location: 40, length: 44)
Lastly, I try to retrieve attributes for the text
// retrieve attributes
let attributes1 = someText.attributes(at: 0, effectiveRange: &range1)
// iterate each attribute
print("attributes1")
for attr in attributes1 {
print(attr.key, attr.value)
}
let attributes2 = someText.attributes(at: 0, effectiveRange: &range2)
// iterate each attribute
print("attributes2")
for attr in attributes2 {
print(attr.key, attr.value)
}
let attributes3 = someText.attributes(at: 0, effectiveRange: &range3)
// iterate each attribute
print("attributes3")
for attr in attributes3 {
print(attr.key, attr.value)
}
I get the following results. In all cases showing only the first set of attributes.
attributes1
NSAttributedStringKey(_rawValue: NSColor) UIExtendedSRGBColorSpace 0 0 1 1
NSAttributedStringKey(_rawValue: NSFont) font-family: ".SFUIText-Semibold"; font-weight: bold; font-style: normal; font-size: 12.00pt
attributes2
NSAttributedStringKey(_rawValue: NSColor) UIExtendedSRGBColorSpace 0 0 1 1
NSAttributedStringKey(_rawValue: NSFont) font-family: ".SFUIText-Semibold"; font-weight: bold; font-style: normal; font-size: 12.00pt
attributes3
NSAttributedStringKey(_rawValue: NSColor) UIExtendedSRGBColorSpace 0 0 1 1
NSAttributedStringKey(_rawValue: NSFont) font-family: ".SFUIText-Semibold"; font-weight: bold; font-style: normal; font-size: 12.00pt
What do I need to do to get all of the attributes in the string?
It has been suggested I use enumerate attributes. That does not seem to be legal. See below:

attributes(at:, effectiveRange:)method that you didn't understand. It take the attributes at the placeat, and with effectiveRange, that's something else. So at 0, for the first two tries, you get the same, that's normal. To get all the attributes, useenumerateAttributes(in:options:using:)where you set the range from 0 to the length. - Larmelet attribute4 = someText.enumerateAttributes(in:options:using:), but you can dosomeText.enumerateAttributes(in:options:using:)- Larmerangeparameter is a pointer, meaning you don't put value in it, it will have afterwards the range corresponding. - Larme