iOS低版本下NSAttributedString解析HTML标签并添加样式的问题
问题描述
我有如下本地化字符串:
"Register and get <b>all</b> <b>rewards cards</b> of our partners <b>in one</b> universal <b>card</b>"
其中部分内容需要加粗显示,同时要设置自定义段落样式(行间距、居中对齐、最小行高)。
目前我有两段代码:
- 能实现段落样式但无法处理HTML加粗标签:
let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = 1.0 paragraphStyle.alignment = .center paragraphStyle.minimumLineHeight = 18.0 let attributedString = NSMutableAttributedString(string: descriptionString, attributes: [.font: UIFont.proximaNovaRegularWithSize(size: 15.0), .paragraphStyle: paragraphStyle])
- 能解析HTML标签的方法,但无法和自定义样式结合生效:
func convertFromHTMLString(_ input: String?) -> NSMutableAttributedString? { guard let input = input else { return nil } guard let data = input.data(using: String.Encoding.unicode, allowLossyConversion: true) else { return nil } return try? NSMutableAttributedString(data: data, options: [NSAttributedString.DocumentReadingOptionKey.documentType : NSAttributedString.DocumentType.html], documentAttributes: nil) }
我尝试通过defaultAttributes同时设置字体和段落样式,但并未生效,字体和自定义段落样式都没有被应用,效果不符合预期。
注:App需要兼容iOS 15以下版本,无法使用Markdown语法。
解决方案
问题出在HTML解析生成富文本时,defaultAttributes优先级较低,解析器会用系统默认样式覆盖自定义设置。正确做法是先解析HTML得到带加粗格式的富文本,再遍历统一添加全局样式,同时保留加粗部分的特殊字体。
具体实现代码
func convertHTMLToStyledAttributedString(_ input: String?) -> NSMutableAttributedString? { guard let input = input else { return nil } // 1. 解析HTML标签,生成带加粗格式的基础富文本 guard let data = input.data(using: .utf8, allowLossyConversion: true) else { return nil } let htmlOptions: [NSAttributedString.DocumentReadingOptionKey: Any] = [ .documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue ] guard let attributedString = try? NSMutableAttributedString(data: data, options: htmlOptions, documentAttributes: nil) else { return nil } // 2. 定义全局样式参数 let baseFont = UIFont.proximaNovaRegularWithSize(size: 15.0) let boldFont = UIFont.proximaNovaBoldWithSize(size: 15.0) // 需确保项目中有对应的加粗字体 let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = 1.0 paragraphStyle.alignment = .center paragraphStyle.minimumLineHeight = 18.0 // 3. 遍历富文本,统一设置样式并保留加粗特性 attributedString.enumerateAttributes(in: NSRange(location: 0, length: attributedString.length), options: []) { attributes, range, _ in var newAttributes = attributes // 强制设置自定义段落样式 newAttributes[.paragraphStyle] = paragraphStyle // 根据原有字体特性替换为自定义字体:加粗文本用自定义加粗字体,其余用常规字体 if let existingFont = attributes[.font] as? UIFont, existingFont.fontDescriptor.symbolicTraits.contains(.traitBold) { newAttributes[.font] = boldFont } else { newAttributes[.font] = baseFont } attributedString.setAttributes(newAttributes, range: range) } return attributedString }
关键说明
- 先解析后样式:HTML解析会生成带默认格式的富文本,后续遍历修改能确保自定义样式覆盖系统默认值,同时保留
<b>标签的加粗效果。 - 自定义字体匹配:解析
<b>标签后系统会自动添加加粗字体特性,需替换为项目使用的自定义加粗字体,避免显示系统默认加粗样式。 - 低版本兼容:该方案不依赖iOS 15+的Markdown API,适配更早的系统版本。
内容的提问来源于stack exchange,提问作者nastassia
相关产品推荐
相关产品推荐

