'Trying to convert HTML to AttributedString within a UIViewRepresentable in SwiftUI
I'm trying to create this UIViewRepresentable view with an UILabel so that I can reprersent an NSAttributedString using SwiftUI.
I've tried to create a function that converts this but it doesn't work.
extension Data {
var html2AttributedString: NSAttributedString? {
do {
return try NSAttributedString(data: self, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)
} catch {
print("error:", error)
return nil
}
}
var html2String: String {
return html2AttributedString?.string ?? ""
}
}
extension String {
var html2AttributedString: NSAttributedString? {
return Data(utf8).html2AttributedString
}
var html2String: String {
return html2AttributedString?.string ?? ""
}
var noHTML: String {
let str = self.replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression, range: nil)
return str
}
}
This is what I get when I have a List going though the records given by the JSON.
As soon as I don't use the html2AttributedString, all works great (HTML text is displayed).
It seems I can't get the NSAttributedString(data: self, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)
part working.
=== AttributeGraph: cycle detected through attribute 38 ===
=== AttributeGraph: cycle detected through attribute 38 ===
=== AttributeGraph: cycle detected through attribute 41 ===
=== AttributeGraph: cycle detected through attribute 19 ===
=== AttributeGraph: cycle detected through attribute 33 ===
=== AttributeGraph: cycle detected through attribute 38 ===
=== AttributeGraph: cycle detected through attribute 19 ===
Solution 1:[1]
I was experiencing the same error using the Down library to convert markdown to an attributed string (which under the hood is converting the markdown to HTML to an attributed string). I had to explicitly wrap the code that converted the markdown and set the attributed string in a DispatchQueue.main.async {}
block to get rid of the AttributeGraph errors. I'm not sure why the errors are occurring in the first place, but it seems thread related.
I'm not sure if this would help your specific case, but it might be worth wrapping the part of your code where you set the attributed string in the label inside a DispatchQueue.
Solution 2:[2]
Elaborating a bit more on previous answer here is another possibility. The idea is the same, just make the conversion from String to NSAttributedString in the main queue. That solved my issues.
struct InfoView: View {
@State private var htmlInfoAttributed: NSAttributedString?
@ObservedObject var model: SomeModel
var body: some View {
VStack(alignment: .leading, spacing: 6) {
if let string = htmlInfoAttributed,
let attr = try? AttributedString(string, including: \.uiKit) {
Text(attr)
}
}
.onAppear {
DispatchQueue.main.async {
if let attributedText = model.htmlString?.toHTMLAttributedString() {
htmlInfoAttributed = attributedText
}
}
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Scott K. |
Solution 2 | Gabriel |