简体   繁体   中英

Refreshing PDFViewer on SwiftUI UIViewRepresentable

I have created a SwiftUI wrapper for creating and displaying PDFs. I have a couple of functionalities that output the new pdf as Data. I have a binding to my PDFViewer but it is not working as expected. The challenge comes when I want to refresh the view (for example I added new text, so the binding data changes) without calling 'updateUIView'. I would like to solve it without calling updateUIView as I would like to do not create PDFDocument(data: data) again if possible.

  • I have researched about delegates and did not find any 'update' or similar function.
  • I also tried layoutDocumentView without success
  • Would like a solution that refreshes the view without creating the doc again
  • Would also have access to the currentPage in a better way if possible (now I am working with Notifications)
struct PDFViewer: UIViewRepresentable {
    typealias UIViewType = PDFView
    
    @Binding var data: Data
    @Binding var currentPageNumber: Int?
    
    var pdfView: PDFView
    let singlePage: Bool
    
    init(pdfView: PDFView, data: Binding<Data>, singlePage: Bool = false, currentPage: Binding<Int?>) {
        self.pdfView = pdfView
        self._data = data
        self.singlePage = singlePage
        self._currentPageNumber = currentPage
    }
    
    func makeUIView(context: UIViewRepresentableContext<PDFViewer>) -> UIViewType {
        pdfView.autoScales = true
        if singlePage {
            pdfView.displayMode = .singlePage
        }
        pdfView.delegate = context.coordinator
        pdfView.document = PDFDocument(data: data) // <- DO NOT REFRESH EVEN IF DATA CHANGES
        
        NotificationCenter.default.addObserver(forName: .PDFViewSelectionChanged, object: nil, queue: nil) { (notification) in
            DispatchQueue.main.async {
                let newPage = (pdfView.currentPage?.pageRef!.pageNumber)!
                print(newPage)
                if currentPageNumber != newPage {
                    currentPageNumber = newPage
                }
            }
        }
        return pdfView
    }
    
    func updateUIView(_ pdfView: UIViewType, context _: UIViewRepresentableContext<PDFViewer>) {
////        let newPDFDoc = PDFDocument(data: data) <---- DO NOT WANT TO CREATE IT AGAIN
//        if pdfView.document?.dataRepresentation() != newPDFDoc?.dataRepresentation() {
////            pdfView.document = newPDFDoc
////            pdfView.go(to: pdfView.currentPage!)
//        }
    }
    
    class Coordinator: NSObject, PDFViewDelegate, UIGestureRecognizerDelegate {
        var parent: PDFViewer
        
        init(_ parent: PDFViewer) {
            self.parent = parent
        }
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
}

you could try something very simple like this approach, to not refresh the view even when data changes:

@State private var firstTimeOnly = true

....

func updateUIView(_ pdfView: UIViewType, context _: UIViewRepresentableContext<PDFViewer>) {
    if self.firstTimeOnly {
        self.firstTimeOnly = false
        let newPDFDoc = PDFDocument(data: data) // <---- DO NOT WANT TO CREATE IT AGAIN
        if pdfView.document?.dataRepresentation() != newPDFDoc?.dataRepresentation() {
            pdfView.document = newPDFDoc
            pdfView.go(to: pdfView.currentPage!)
        }
    }
}

Similarly in makeUIView .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM