在 SwiftUI 中显示 HTML 文本导致属性循环或崩溃

问题描述 投票:0回答:1

我需要能够使用 SwiftUI 文本视图显示 HTML 标记文本。 根据教程,我使用

UIViewRepresentable
找到了这个
NSAttributedString
解决方案。

struct HTMLText: UIViewRepresentable {
    var attributedText: NSAttributedString

    init(text: String) {
        self.attributedText = text.htmlToAttributedString
    }

    func makeUIView(context: Context) -> UITextView {
        let uiTextView = UITextView()

        uiTextView.backgroundColor = .red
        uiTextView.textContainerInset = .zero
        uiTextView.isEditable = false
        uiTextView.isScrollEnabled = false
        uiTextView.textContainer.lineFragmentPadding = 0

        return uiTextView
    }

    func updateUIView(_ uiTextView: UITextView, context: Context) {
        uiTextView.attributedText = attributedText
    }

}

extension String {
    var htmlToAttributedString: NSAttributedString {
        guard let data = data(using: .utf8) else {
            return NSAttributedString(string: self) }
        do {
            return try NSAttributedString(
                data: data,
                options: [.documentType: NSAttributedString.DocumentType.html,
                          .characterEncoding:String.Encoding.utf8.rawValue],
                documentAttributes: nil)
        } catch {
            return NSAttributedString(string: self)
        }
    }
}

虽然这对于简单视图效果很好,但我在将其合并到我的应用程序中时遇到了困难。与

NavigationStack
有关的某些事情会导致属性图中出现循环:
=== AttributeGraph: cycle detected through attribute 96280 ===
。在我的应用程序中,记录了几十条这样的消息,并且没有显示文本字段。更致命的是,直接用作父视图似乎会导致
GeometryReader
,日志记录为
SIGABRT
此复制会导致循环,尽管只有少数并且显示文本:

precondition failure: setting value during update: 768

这会导致完全崩溃。

struct ContentView: View { @State var showView: Bool = false var body: some View { NavigationStack { Button(action: { showView.toggle() }, label: { Text("Show view") }) .navigationDestination(isPresented: $showView, destination: { ScrollableView() // Putting the scroll view here directly seems to be fine }) } } } struct ScrollableView: View { var body: some View { ScrollView { HTMLText(text: "hello <em> world </em>") } } }

出问题的确切点是尝试将字符串数据编码到属性字符串中,即使它被包装在 try 块中,但这里似乎根本没有处理错误。我无法找到其他方式来显示 HTML 文本,我还有其他选择吗?我可以采取哪些步骤来尝试调试属性图?

ios swift swiftui mobile uikit
1个回答
0
投票
struct Crash: View { var body: some View { GeometryReader { _ in HTMLText(text: "hello <em> world </em>") } } }

时,你可以看到内部函数

htmlToAttributedString
调用。根据它的名字,我认为它的工作是强制 UI 立即重新加载。这将导致
_UIHostingView.requestImmediateUpdate
,如该日志记录
cycle
所示。正如您所看到的,将调试断点放在
AttributeGraph: cycle detected through attribute
init
中:

enter image description here 一个

HTMLText

将导致另一个

ScrollableView.body.getter

enter image description here 要摆脱这个问题,我的建议是将您的

ScrollableView.body.getter

放入

htmlToAttributedString
:
DispatchQueue.main.async

	
© www.soinside.com 2019 - 2024. All rights reserved.