Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI attributed string from HTML crashes the app

Tags:

ios

swift

swiftui

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?

like image 408
Chris Avatar asked Jan 14 '20 09:01

Chris


People also ask

Does SwiftUI support myattributedstring?

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.

How to create an attributed string in SwiftUI with markdown?

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.

When to use uiviewrepresentable in SwiftUI?

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.

How do I concatenate text views in SwiftUI?

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.


1 Answers

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

like image 102
Pushpendra Avatar answered Oct 11 '22 12:10

Pushpendra