如何解决UITextView因HTML富文本切换到TextKit 1兼容模式问题?
解决UITextView因HTML生成的富文本切换到TextKit 1兼容模式的问题
当使用NSAttributedString的documentType: NSAttributedString.DocumentType.html选项生成富文本并赋值给UITextView时,会收到以下日志:
UITextView is switching to TextKit 1 compatibility mode because its textStorage contains attributes which are not compatible with TextKit 2
示例代码如下:
func makeUIView(context _: Context) -> UITextView { let textView = UITextView() return textView } func updateUIView(_ uiView: UITextView, context _: Context) { var currentText: NSAttributedString? let htmlString = "<html><body><h1>Example</h1></body></html>" guard let encodedData = htmlString.data(using: .utf8) else { fatalError("Could not encode HTML data") } do { currentText = try NSAttributedString(data: encodedData, options: [ .documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue ], documentAttributes: nil) } catch let error as NSError { fatalError(error.localizedDescription) } catch { fatalError("error") } uiView.attributedText = currentText }
可行解决办法
1. 手动过滤不兼容属性
HTML解析生成的富文本会包含部分TextKit 2不支持的私有属性或特殊附件属性,遍历并保留已知兼容的属性即可解决:
func sanitizeAttributedString(_ attributedString: NSAttributedString) -> NSAttributedString { let mutableAttributedString = NSMutableAttributedString(attributedString: attributedString) mutableAttributedString.enumerateAttributes(in: NSRange(location: 0, length: mutableAttributedString.length), options: []) { attributes, range, _ in let filteredAttributes = attributes.filter { key, _ in // 保留TextKit 2明确支持的属性 switch key { case .font, .foregroundColor, .backgroundColor, .paragraphStyle, .link, .kern, .strikethroughStyle, .underlineStyle: return true default: return false } } mutableAttributedString.setAttributes(filteredAttributes, range: range) } return mutableAttributedString }
使用时在赋值前调用:
if let sanitizedText = currentText.map(sanitizeAttributedString) { uiView.attributedText = sanitizedText }
2. 强制启用TextKit 2(需配合属性清理)
显式为UITextView配置TextKit 2组件,但如果富文本仍有不兼容属性可能导致显示异常,建议和属性过滤配合使用:
func makeUIView(context _: Context) -> UITextView { let textContainer = NSTextContainer() let textView = UITextView(frame: .zero, textContainer: textContainer) textView.textLayoutManager = NSTextLayoutManager() textView.textContainerInset = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8) return textView }
3. 自定义HTML解析逻辑
使用第三方库(如SwiftSoup)手动解析HTML并构建富文本,完全控制生成的属性,从根源避免不兼容问题:
import SwiftSoup func htmlToAttributedString(_ html: String) throws -> NSAttributedString { let doc = try SwiftSoup.parse(html) let mutableString = NSMutableAttributedString() // 解析h1标签并设置对应样式 if let h1Element = try doc.select("h1").first() { let h1Text = try h1Element.text() let h1Attributes: [NSAttributedString.Key: Any] = [ .font: UIFont.boldSystemFont(ofSize: 24), .foregroundColor: UIColor.black ] mutableString.append(NSAttributedString(string: h1Text, attributes: h1Attributes)) } // 可扩展解析其他HTML标签(p、a等) return mutableString }
内容的提问来源于stack exchange,提问作者user8675
相关产品推荐
相关产品推荐

