在 SwiftUI UIViewRepresentable 上刷新 PDFViewer

Posted

技术标签:

【中文标题】在 SwiftUI UIViewRepresentable 上刷新 PDFViewer【英文标题】:Refreshing PDFViewer on SwiftUI UIViewRepresentable 【发布时间】:2022-01-22 14:01:30 【问题描述】:

我创建了一个用于创建和显示 PDF 的 SwiftUI 包装器。我有几个功能可以将新的 pdf 作为数据输出。我绑定了我的 PDFViewer,但它没有按预期工作。当我想刷新视图(例如我添加了新文本,因此绑定数据更改)而不调用“updateUIView”时,挑战就来了。我想在不调用 updateUIView 的情况下解决它,因为如果可能的话,我不想再次创建 PDFDocument(data: data)。

我研究了代表,没有发现任何“更新”或类似功能。 我也试过 layoutDocumentView 没有成功 想要一种无需再次创建文档即可刷新视图的解决方案 如果可能的话,还可以以更好的方式访问 currentPage(现在我正在使用通知)
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)
    

【问题讨论】:

【参考方案1】:

你可以尝试一些非常简单的方法,比如不刷新视图 即使数据发生变化:

@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!)
        
    

makeUIView 中类似。

【讨论】:

以上是关于在 SwiftUI UIViewRepresentable 上刷新 PDFViewer的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI - 如何在 SwiftUI 中弹出到特定视图?

SwiftUI - SwiftUI 中是不是有等效的 popViewController?

SwiftUI - 在 SwiftUI 中对显示的 JSON 文件进行排序,分节或排序

如何在 SwiftUI 中使用 Realm

在 SwiftUI 中滑动列表时隐藏导航栏

如何在 SwiftUI 的 ScrollView 中制作动画? SwiftUI 中的手风琴风格动画