求助: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
相关产品推荐
相关产品推荐

