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:)
– Larmerange
parameter is a pointer, meaning you don't put value in it, it will have afterwards the range corresponding. – Larme