Based on the two answers of @Tomas in this question, I write the following code to render user input as HTML. The HTMLStringView
method works fine, but the HTMLText
doesn't update when fullText
changes.
I have two questions:
(1) Why does HTMLStringView
method works normally (that is, always get sync with user input)?
(2) And why does HTMLText
fails? How should I fix it?
Below are the code.
import SwiftUI
struct Test: View {
@State private var placeholderString: String = "Insert here"
@State private var fullText: String = ""
var body: some View {
VStack {
ZStack(alignment: .top) {
if fullText.isEmpty {
TextEditor(text: $placeholderString)
.padding(.top, 20)
}
TextEditor(text: $fullText)
.padding(.top, 20)
.autocapitalization(.none)
.opacity(fullText.isEmpty ? 0.5 : 1)
}
HTMLText(html: """
<html>
<head>
</head>
<body>
<p>
//Does not update
\(fullText)
</p>
</body>
</html>
""")
HTMLStringView(htmlContent: """
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>MathJax example</title>
<script>MathJax = {
tex:{
inlineMath: [['$', '$'], ['\\(', '\\)']],
tags: 'ams'
},
svg:{
fontCache: 'global'
}
};
</script>
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
<script id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js">
</script>
</head>
<body>
<p>
\(fullText.replacingOccurrences(of: "\n\n", with: "<br />"))
</p>
</body>
</html>
""")
}
}
}
struct Test_Previews: PreviewProvider {
static var previews: some View {
Test()
}
}
Here are the HTMLText.swift
and HTMLStringView.swift
.
// convert html to attributed string and show in a UITextView
import SwiftUI
struct HTMLText: UIViewRepresentable {
let html: String
func makeUIView(context: UIViewRepresentableContext<Self>) -> UITextView {
let view = UITextView()
DispatchQueue.main.async {
let data = Data(self.html.utf8)
if let attributedString = try? NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html], documentAttributes: nil) {
// view.attributedText = attributedString
view.textStorage.append(attributedString)
}
}
return view
}
func updateUIView(_ uiView: UITextView, context: Context) {}
}
// render html directly
import WebKit
import SwiftUI
struct HTMLStringView: UIViewRepresentable {
let htmlContent: String
func makeUIView(context: Context) -> WKWebView {
return WKWebView()
}
func updateUIView(_ uiView: WKWebView, context: Context) {
uiView.loadHTMLString(htmlContent, baseURL: nil)
}
}