NSAttributedString忽略HTML标签内样式问题:保留TM上标6px字号并应用自定义字体
Hey there! I totally get where you're coming from—applying a global font but losing those tiny TM styles is super frustrating. Let's fix this step by step.
The Core Issue
When you call addAttributes([.font : font], range: NSMakeRange(0, mutable.length)), you're overwriting all existing font-related attributes across the entire string, including the 6px font size set by your <sup> tag. Instead, we need to only apply the custom font to parts of the string that don't already have their own font styling.
Step-by-Step Fix
Here's how you can preserve the HTML-derived styles while applying your custom font to the rest:
First, parse your HTML into an NSMutableAttributedString as before
let newText = "My new trade mark is MELLON<sup style=\"font-size:6px\">TM</sup> Corporation" guard let data = newText.data(using: .utf8) else { return } let attrString = try? NSMutableAttributedString( data: data, options: [ NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.html, NSAttributedString.DocumentReadingOptionKey.characterEncoding: String.Encoding.utf8.rawValue, ], documentAttributes: nil ) guard let mutableAttrString = attrString else { return }Define your custom font
let customFont = UIFont(name: "YourCustomFontName", size: 10)! // Replace with your font and sizeTraverse the string and apply font only where it's missing
We'll useenumerateAttributesto check each segment of the string. For segments that don't have an existing.fontattribute, we'll apply our custom font:mutableAttrString.enumerateAttributes(in: NSRange(location: 0, length: mutableAttrString.length), options: []) { attributes, range, stop in // Check if the segment already has a font attribute if attributes[.font] == nil { mutableAttrString.addAttribute(.font, value: customFont, range: range) } // Optional: Adjust baseline offset for better sup tag alignment (matches HTML's <sup> behavior) if let existingFont = attributes[.font] as? UIFont, existingFont.pointSize == 6 { mutableAttrString.addAttribute(.baselineOffset, value: 4, range: range) // Tweak value to fit your design } }Assign to your label
label.attributedText = mutableAttrString
Why This Works
The enumerateAttributes method iterates through every contiguous segment of the string that has the same set of attributes. By checking if a segment already has a .font attribute, we avoid overwriting the styles from your <sup> tag. The optional baseline offset adjustment ensures the TM sits neatly above the text, just like HTML's <sup> intended.
Bonus: Extend to Other Attributes
If you also want to set global attributes like text color without overriding existing styles, you can reuse this pattern—just check if the target attribute exists before applying it to a segment.
内容的提问来源于stack exchange,提问作者busido

