When does QLPreviewController save data in updateContents mode

148 Views Asked by At

Context

I have a SwiftUI app in which I want to show a PDF and allow the user to enter data and annotate on the PDF.

In order to do this, I wrap a QLPreviewController in a UIViewControllerRepresentable and this renders the PDF in a SwiftUI view.

The form filling and annotation works as desired.

My PDF document is stored in the documents directory and the QLPreviewItemEditingMode I set is updateContents as I want the updates to be made to the original document.

The Issue

I have a save button on my SwiftUI view which renders the PDF, which when tapped, needs to upload this PDF document to a server.

The problem is that none of the changes that the user has made is being saved at this moment and so the document uploaded is not the version the user is seeing on their screen.

In order to debug this, I downloaded the app container from Window -> Devices and Simulators -> Select my App -> Download container

I can see that the PDF file in the documents directory does not have the new data.

However, once I dismiss the SwiftUI view, it seems that the file now has once I check the container again.

Is there anyway to get the latest version / force save the file from the without needing to dismiss the QLPreviewController ?

The didUpdateContentsOf or the didSaveEditedCopyOf never gets called when I input any text data into the form. These only seem to get called when I add drawings or when I dismiss the SwiftUI view which is rather frustrating as I want to know when the text has been updated.

Here is my QLPreviewController if it helps debug this

struct QLPDFPreviewController: UIViewControllerRepresentable {
    let url: URL?
    
    func makeUIViewController(context: Context) -> UINavigationController {
        let controller = QLPreviewController()
        controller.dataSource = context.coordinator
        controller.delegate = context.coordinator
        let navigationController = UINavigationController(rootViewController: controller)
        return navigationController
    }
    
    func updateUIViewController(_ uiViewController: UINavigationController,
                                context: Context) { }
    
    func makeCoordinator() -> Coordinator {
        return Coordinator(parent: self)
    }
    
    class Coordinator: NSObject, QLPreviewControllerDataSource, QLPreviewControllerDelegate {
        let parent: QLPDFPreviewController
        
        init(parent: QLPDFPreviewController) {
            self.parent = parent
        }
        
        func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
            return 1
        }
        
        func previewController(_ controller: QLPreviewController,
                               previewItemAt index: Int) -> QLPreviewItem {
            guard let url = parent.url else { return NSURL(string: "")! }
            return url as NSURL
        }
        
        func previewController(_ controller: QLPreviewController,
                               editingModeFor previewItem: QLPreviewItem) -> QLPreviewItemEditingMode {
            .updateContents
        }
        
        func previewController(_ controller: QLPreviewController,
                               didUpdateContentsOf previewItem: QLPreviewItem) {
            print("did some updates")
        }
        
        // This only gets called after drawing or dismissing the view
        func previewController(_ controller: QLPreviewController,
                               didSaveEditedCopyOf previewItem: QLPreviewItem,
                               at modifiedContentsURL: URL) {
            guard let url = parent.url else { return }
            try? FileManager.default.moveItem(at: modifiedContentsURL, to: url)
            print("moved")
            print()
        }
    }
}
0

There are 0 best solutions below