Q: How to restore last position within document using PDFView and SwiftUI?

I thought about posting this question over at Stack Overflow (and I still may), but the thought of getting a bunch of condescending answers led me to try this first.

There’s not a lot of information out there about integrating PDFKit and SwiftUI. Here’s what I need to do:

  • Wrap PDFView for SwiftUI using UIViewRepresentable and display a PDF that is stored as a binary blob in a Core Data entity (check!).
  • When the user stops viewing the PDF (i.e. when the PDFView disappears), I need to store the scale factor, current page index, and a CGRect representing the section of the page the user is looking at (a CGRect seems easier to save in Core Data than whatever a PDFDestination is). All of those properties can be obtained from the PDFView object, and I’d like to save them in Core Data in the same entity as the PDF data.
  • Next time the user views the PDF, restore it to the same location the user viewed last, at the same zoom level.

Here’s where I’m confused:

  1. I can set the PDFView’s scaleFactor in the “makeUIView” function required for all UIViewRepresentable-conforming structs. How do I set it to display a specific page before it appears? Using the “go(to: PDFPage)” function before returning the PDFView doesn’t seem to work. Putting it in the “update” function would cause it to jump back to the same page every time the view updated.
  2. How can I access the PDFView’s scaleFactor and current page index and save it in Core Data before the view disappears? Can I access the managed object context environment variable in my UIViewRepresentable struct somewhere, or within a Coordinator or something (I don’t currently have a Coordinator set up)?

I just can’t seem to figure out what to do here. There are so many options for communicating at various times: Notifications, bindings, ObservableObjects, the dismantleUIView function, onAppear/onDisappear modifiers… I’m suddenly lost as to how to approach this.

If you think you can help: comments are open! I hope to update this post with a working solution soon.