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
}
}
}