Home > Software design >  How to change the page programmicly in swiftui pdf
How to change the page programmicly in swiftui pdf

Time:02-23

I have a code to display a pdf

  import PDFKit
import SwiftUI

struct PDFKitRepresentedView: UIViewRepresentable {
    typealias UIViewType = PDFView

    let data: Data
    let singlePage: Bool
    var doc:PDFView=PDFView()
    init(_ data: Data, singlePage: Bool = false) {
        self.data = data
        self.singlePage = singlePage
    }

    func makeUIView(context _: UIViewRepresentableContext<PDFKitRepresentedView>) -> UIViewType {
        // Create a `PDFView` and set its `PDFDocument`.
        let pdfView = doc
        pdfView.document = PDFDocument(data: data)
        pdfView.autoScales = true
        if singlePage {
            pdfView.displayMode = .singlePage
        }
        return pdfView
    }
    
    func updateUIView(_ pdfView: UIViewType, context _:                  UIViewRepresentableContext<PDFKitRepresentedView>) {
        pdfView.document = PDFDocument(data: data)
        
      }
    }
    struct ContentView: View {
     var path=Bundle.main.url(forResource: "big", withExtension:  "pdf");
     @State var doc:PDFKitRepresentedView=PDFKitRepresentedView(Data())
     @State var data :Data?;
     var body: some View {
        HStack{
            start(doc: &doc,path: path!)
                .onAppear(perform: {
                    self.data=try?Data(contentsOf: path!);
                    doc.doc.goToNextPage(nil)
                    doc.doc.goToNextPage(nil)
                })
        }
        }
    }

    func start(doc:inout PDFKitRepresentedView,path:URL)->PDFKitRepresentedView{
      doc=try!PDFKitRepresentedView(Data(contentsOf: path));
      return doc;
    }

But I can't seem to find the method to change the page in the showing pdf.I tried go() but it just crashed. I need a button to change the page on click.Sorry I'm new to swiftUI.

CodePudding user response:

you could re-structure your code and use the following approach in adding the page selection from the Buttons, into func updateUIView(...) :

import PDFKit
import SwiftUI

struct PDFKitView: UIViewRepresentable {
    typealias UIViewType = PDFView
    
    @Binding var page: Int
    @State var data: Data
    let singlePage: Bool
    
    func makeUIView(context: UIViewRepresentableContext<PDFKitView>) -> UIViewType {
        let pdfView = PDFView()
        pdfView.document = PDFDocument(data: data)
        pdfView.autoScales = true
        if singlePage {
            pdfView.displayMode = .singlePage
        }
        return pdfView
    }

    func updateUIView(_ view: UIViewType, context: UIViewRepresentableContext<PDFKitView>) {
        if let thePage = view.document?.page(at: page) {
            view.go(to: thePage)
        }
    }
}

struct ContentView: View {
    @State var page = 0
    
    var body: some View {
        VStack {
            HStack {
                Button("Next Page") { page  = 1 } // need to add bounds check
                Button("Prev Page") { page -= 1 } // need to add bounds check
            }.buttonStyle(.bordered)
            PDFKitView(page: $page, data: loadData(), singlePage: true)
        }
    }
    
    private func loadData() -> Data {
        guard let path = Bundle.main.url(forResource: "big", withExtension:  "pdf") else {
            print("Could not find PDF document")
            return Data()
        }
        do {
            return try Data(contentsOf: path)
        } catch {
            print("error: \(error)") // todo
            return Data()
        }
    }
}

EDIT-1:

Another somewhat more flexible approach is to pass a PDFDocument into PDFKitView, such as:

struct PDFKitView: UIViewRepresentable {
    typealias UIViewType = PDFView
    
    @Binding var page: Int
    @Binding var doc: PDFDocument
    let singlePage: Bool
    
    func makeUIView(context: UIViewRepresentableContext<PDFKitView>) -> UIViewType {
        let pdfView = PDFView()
        pdfView.document = doc
        pdfView.autoScales = true
        if singlePage {
            pdfView.displayMode = .singlePage
        }
        return pdfView
    }

    func updateUIView(_ view: UIViewType, context: UIViewRepresentableContext<PDFKitView>) {
        view.document = doc
        if let thePage = view.document?.page(at: page) {
            view.go(to: thePage)
        }
    }
}

struct ContentView: View {
    @State var page = 0
    @State var doc = PDFDocument()
    
    var body: some View {
        VStack {
            HStack {
                Button("Next Page") {
                    if page   1 < doc.pageCount {
                        page  = 1
                    }
                }
                Button("Prev Page") {
                    if page-1 > 0 {
                        page -= 1
                    }
                }
            }.buttonStyle(.bordered)
            PDFKitView(page: $page, doc: $doc, singlePage: true)
        }
        .onAppear {
            loadDoc()
        }
    }
    
    private func loadDoc() {
        guard let path = Bundle.main.url(forResource: "big", withExtension: "pdf") else {
            print("Could not find PDF document")
            return
        }
        do {
            let data = try Data(contentsOf: path)
            if let theDoc = PDFDocument(data: data) {
                doc = theDoc
            }
        } catch {
            print("error: \(error)") // todo
        }
    }
}
  • Related