0

I want to apply a specific font to an NSMutableAttributedString where no .font attribute is applied. How could I achieve that? I tried enumerating the attributes that contain a font and extracting the ranges but I am kind of lost to the complexity of finding the ranges that don't contain a font attribute since I think I must handle intersections or possible unknown scenarios. Is there a simple way to do it? What I did until now:

        var allRangesWithFont = [NSRange]()
        let stringRange = NSRange(location: 0, length: length)
        
        beginEditing()
        enumerateAttribute(.font,
                           in: stringRange,
                           options: .longestEffectiveRangeNotRequired) { (value, range, stop) in
            
            if let f = value as? UIFont {
                allRangesWithFont.append(range)
            }
        }
Bogdan
  • 402
  • 2
  • 8
  • 18

1 Answers1

1

Change your way of thinking, instead, check if the font is not there, and apply your new font directly.

With attrStr being your NSMutableAttributedString, and newFont the font you want to apply.

let newFont = UIFont.italicSystemFont(ofSize: 15)
attrStr.enumerateAttribute(.font, in: NSRange(location: 0, length: attrStr.length), options: []) { value, subrange, pointeeStop in
    guard value == nil else { return }
    attrStr.addAttribute(.font, value: newFont, range: subrange)
}
Larme
  • 24,190
  • 6
  • 51
  • 81
  • That was so obvious, I went on the presumption that `enumerateAttribute ` only returned ranges where the font was found, thanks! The `if let f = value as? UIFont` check was for `CTFont` and other possible font classes but I did not expect it to return the range if no font was set and I did not even check, my bad. – Bogdan Apr 01 '21 at 10:26
  • You are enumerating on `NSAttributedStringKey.font`, so value will be a `UIFont?`. If you enumerate all attributes, then, indeed you need to check `as? UIFont`. – Larme Apr 01 '21 at 10:31