You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 06:15:32