I am working on an app which allows the user to write some markup language and have a PDF document generated out of it, and I want to have a real-time preview of the PDF document.
I used PDFView
in PDFKit with UIViewRepresentable
to use it in SwiftUI.
import PDFKit
import SwiftUI
struct DocumentView: UIViewRepresentable {
@Binding var source: String
func generateDocument() -> PDFDocument? {
let pdfRenderer = UIGraphicsPDFRenderer(bounds: CGRect(x: 0, y: 0, width: 595, height: 842))
let data = pdfRenderer.pdfData { context in
context.beginPage()
let attributes = [
NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 16)
]
// adding text to pdf
let text = source
text.draw(at: CGPoint(x: 20, y: 50), withAttributes: attributes)
}
return PDFDocument(data: data)
}
func makeUIView(context: UIViewRepresentableContext<DocumentView>) -> PDFView {
let pdfView = PDFView()
pdfView.document = generateDocument()
return pdfView
}
func updateUIView(_ uiView: PDFView, context: UIViewRepresentableContext<DocumentView>) {
uiView.document = generateDocument()
}
}
In my ContentView
, I basically just have this:
import SwiftUI
struct ContentView: View {
@State var source: String = ""
var body: some View {
HStack {
TextEditor(text: $source)
DocumentView(source: $source)
}
}
}
where TextEditor
is for text editing and DocumentView
is for displaying the preview.
Every time the PDF document gets updated (after a source
change), DocumentView
will get focused for an instance (I can verify it with a FocusState
and a onChange()
), which basically removes the focus from the text editor and interrupts the input process (for example, if I’m typing with the onscreen keyboard, it would be closed), and it seems that this is caused by uiView.document = generateDocument()
in updateUIView
.
Is there a way to change this behavior? I tried to disable the DocumentView, set it to .focusable(false)
, and none of it worked. Thanks.