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

求助:iOS 14+ SwiftUI无需WebKit渲染带DataDetector的TextView及HTML文本

iOS 14 SwiftUI HTML文本渲染问题解决方案

1. 解决SwiftSoup丢失<br/>标签的问题

SwiftSoup默认的text()方法会过滤掉<br/>这类格式标签,你需要手动遍历DOM节点,遇到<br/>时主动插入换行符:

import SwiftSoup

func htmlToFormattedString(_ html: String) throws -> String {
    let doc = try SwiftSoup.parse(html)
    var result = ""
    for node in doc.body()!.childNodes() {
        if let element = node as? Element {
            if element.tagName() == "br" {
                result += "\n"
            } else {
                result += try element.text()
            }
        } else if let textNode = node as? TextNode {
            result += textNode.text()
        }
    }
    return result
}

如果需要保留链接等富文本格式,不要转成纯文本,直接用系统API从HTML数据生成NSAttributedString,它会自动识别<br/>并转换为换行:

func htmlToAttributedString(_ html: String) throws -> NSAttributedString {
    guard let data = html.data(using: .utf8) else { 
        throw NSError(domain: "HTMLParseError", code: 0, userInfo: nil) 
    }
    let options: [NSAttributedString.DocumentReadingOptionKey: Any] = [
        .documentType: NSAttributedString.DocumentType.html,
        .characterEncoding: String.Encoding.utf8.rawValue
    ]
    return try NSAttributedString(data: data, options: options, documentAttributes: nil)
}

2. 解决手动插入换行后链接格式丢失的问题

不要直接修改纯文本再重新生成富文本,而是直接操作NSMutableAttributedString插入换行,完整保留原有属性:

func insertLineBreak(in attrString: NSAttributedString, at index: Int) -> NSMutableAttributedString {
    let mutableAttr = NSMutableAttributedString(attributedString: attrString)
    let lineBreak = NSAttributedString(string: "\n")
    mutableAttr.insert(lineBreak, at: index)
    return mutableAttr
}

如果需要批量处理换行,优先依赖系统HTML解析的结果,避免手动修改字符串破坏属性范围。

在SwiftUI中使用

将生成的NSAttributedString用UIViewRepresentable包装为SwiftUI视图:

struct AttributedText: UIViewRepresentable {
    let attributedString: NSAttributedString
    
    func makeUIView(context: Context) -> UITextView {
        let textView = UITextView()
        textView.attributedText = attributedString
        textView.isEditable = false
        textView.isScrollEnabled = false
        textView.backgroundColor = .clear
        return textView
    }
    
    func updateUIView(_ uiView: UITextView, context: Context) {
        uiView.attributedText = attributedString
    }
}

// 使用示例
if let attrString = try? htmlToAttributedString("<p>第一行内容<br/>第二行内容<a href='xxx'>跳转链接</a></p>") {
    AttributedText(attributedString: attrString)
}

内容的提问来源于stack exchange,提问作者Eli017

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 10:15:40