I'm trying to convert HTML
formatted text into an attributed string, and insert it into a SwiftUI
view.
Firstly I have a String
extension that converts the HTML
string to NSAttributedString
:
extension String {
func convertHtml() -> NSAttributedString {
guard let data = data(using: .utf8) else { return NSAttributedString() }
if let attributedString = try? NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html], documentAttributes: nil) {
return attributedString
} else {
return NSAttributedString()
}
}
}
Then I have created a HTMLLabel
view:
struct HTMLLabel: UIViewRepresentable {
let html: String
func makeUIView(context: UIViewRepresentableContext<Self>) -> UILabel {
let label = UILabel()
label.attributedText = html.convertHtml()
return label
}
func updateUIView(_ uiView: UILabel, context: UIViewRepresentableContext<Self>) {}
}
Then I insert a test into my SwiftUI view:
HTMLLabel(html: "<html><body><b>Hello</b> <i>World</i></body></html>")
The code crashes each time on if let attributedString = try? ...
with EXC_BAD_INSTRUCTION
. I made a test in an empty storyboard project like this:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let label = UILabel(frame: CGRect(x: 50, y: 50, width: 320, height: 50))
label.attributedText = "<html><body><b>Hello</b> <i>World</i></body></html>".convertHtml()
view.addSubview(label)
}
}
That code executes without any issues. Why doesn't the code work in a SwiftUI
context?
Because we are now using macOS, myAttributedString is created with a slightly modified code. It is the same, but replacing UIColor with NSColor and UIFont with NSFont: SwiftUI is far from supporting attributed strings, but with a little effort, we can get at least a little closer.
To create an attributed string in Markdown, you write the code like this: And, you can mix Markdown and apply your preferred styling to the text. Here is an example that highlights some text with various colors: SwiftUI’s text component has a built-in support for AttributedString.
For example, if the attributed string has a hyperlink, this solution will flat-out ignore it. If you are unfortunate to have an unsupported attribute, you may need to use the next approach. When we exhaust all SwiftUI resources, it may be time to create a UIViewRepresentable.
In 2020, SwiftUI added the ability to concatenate Text views. Adding two Text views together results in a new Text view: struct ContentView: View { var body: some View { Text("Hello ") + Text("world!") } } However, not all modifiers will work, only those that return Text.
Use This:-
struct HTMLLabel: UIViewRepresentable {
let html: String
func makeUIView(context: UIViewRepresentableContext<Self>) -> UILabel {
let label = UILabel()
DispatchQueue.main.async {
if let attributedText = self.html.convertHtml() {
label.attributedText = attributedText
}
}
return label
}
func updateUIView(_ uiView: UILabel, context: UIViewRepresentableContext<Self>) {}
}
NSAttributedString.DocumentType.html is Only Work with Main Thread That's why you are getting crash
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With