I made a viewer app that displays a PDF

TL;DR

I will explain about that.

demo

Image from Gyazo

Click here for the source> https://github.com/dropcontrol/PDFViewer

From the explanation of View

struct ContentView: View {
    @ObservedObject var pdfInfo: PDFInfo = PDFInfo()
    
    var body: some View {
        VStack {
            ShowPDFView(pdfInfo: pdfInfo)
            PdfInfoView(pdfInfo: pdfInfo)
            .padding()
        }.onAppear(){
            pdfInfo.addObserver()
        }
        
    }
}

The view that becomes the parent calls two views. One is ShowPDFView (), which is the viewer part of the PDF, and the other is PdfInfoView (), which displays the page number and TOP button below it. So I'm passing pdfInfo: pdfInfo there, but it's on the View

@ObservedObject var pdfInfo: PDFInfo = PDFInfo()

In the part of, @ObservedObject creates an instance ofPDFInfo (), which is ObservableObject. And that PDFInfo () is ...

class PDFInfo: ObservableObject {
    @Published var pageNo: Int = 1
    @Published var pdfView: PDFView = PDFView()
    @Published var stateTopButton: Bool = false
    
    func addObserver() {
        NotificationCenter.default.addObserver(self, selector: #selector(self.pageChanged(_:)), name: Notification.Name.PDFViewPageChanged, object: nil)
    }
    
    @objc func pageChanged(_ notification: Notification) {
        pageNo = pdfView.currentPage!.pageRef!.pageNumber
        stateTopButton = pdfView.canGoToFirstPage
        print(self.pageNo)
        print("page is changed")
    }
}

It looks like this. @Publised creates variables such as pageNo, pdfView, and stateTopButton. Below that, we define a function of func addObserver () {} that registers with the Notification Center, and a function of @objc func pageChanged (_ notification: Notification) {} that is executed when notification is received. Among them are the page number and canGoToFirstPage to determine if it is the top page of the PDF.

So, in this, it is necessary to display PDF,

@Published var pdfView: PDFView = PDFView()

I am making. So, it is initialized with the previous @ ObservedObject. Because I want to reuse pdfInfo in otherViews, I pass it to the View that is reading pdfInfo.

About other views

Since PdfInfoView is in the UI, I think you can understand it by reading the source, so I will omit it and explain ShowPDFView. Here it looks like this:

struct ShowPDFView: View {
    @ObservedObject var pdfInfo: PDFInfo
    
    var body: some View {
        PDFViewer(pdfInfo: pdfInfo)
    }
}

The parent has passed pdfInfo to the @ ObservedObject var pdfInfo: PDFInfo prepared here. I don't see many samples that pass an instance from the parent even if I investigate the case of reusing the instance with @ ObservedObject, but if I do not do this, I can not refer to the variable set in the previous ObservableObject.

So, here, PDFViewer (pdfInfo: pdfInfo) is used to display the actual PDF.

About PDFViewer ()

Regarding PDF settings, the writing method with UIViewController etc. is almost the same, but

struct PDFViewer: UIViewRepresentable {
    @ObservedObject var pdfInfo: PDFInfo
    
    let url: URL = Bundle.main.url(forResource: "Oz was Wizard - Original Soundtrack", withExtension: "pdf")!
    
    func makeUIView(context: UIViewRepresentableContext<PDFViewer>) -> PDFViewer.UIViewType {
<PDF settings here>
    }
    
    func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<PDFViewer>) {
    }
    
}

It is implemented using UIViewRepresentable in the form of. reference:

When using UIKit, it seems that you should write it in the same way. Please refer to the source and other resources for PDF settings.

What I couldn't do with this sample

I wanted to disable the PDF scaling feature, but this isn't functionally implemented in PDFKit, so I'm still looking into it, but I'd be happy if anyone could tell me how to do it.

Recommended Posts

I made a viewer app that displays a PDF
I made a chat app.
I made a shopify app @java
I made a matching app (Android app)
[Android] I made a pedometer app.
I made a rock-paper-scissors app with kotlin
I made a calculator app on Android
I made a rock-paper-scissors app with android
I made an app to scribble with PencilKit on a PDF file
I made a library that works like a Safari tab !!
I made a Wrapper that calls KNP from Java
I made a mod that instantly calls a vehicle with Minecraft
Ruby: I made a FizzBuzz program!
I created a PDF in Java.
I made a simple recommendation function.
I made a package.xml generation tool.
[Rails] I made a simple calendar mini app with customized specifications.
I recently made a js app in the rumored Dart language
I made a source that automatically generates JPA Entity class files
I made a question that can be used for a technical interview
[Ruby] I made a simple Ping client
I made a risky die with Ruby
I made a plugin for IntelliJ IDEA
I made a new Java deployment tool
I made a class that can use JUMAN and KNP from Java
I made a bulletin board using Docker 1
I made a class that automatically generates Json that specifies Minecraft texture etc. [1.12.2]
I made a site that summarizes information on carbohydrate restriction with Vue.js
I will expose the fucking app that I made hard to get a job as an engineer from inexperienced.
I made a THETA API client that can be used for plug-in development
A simple example of a Servlet that displays Japanese
I made a Diff tool for Java files
I made a primality test program in Java
04. I made a front end with SpringBoot + Thymeleaf
I made a mosaic art with Pokemon images
I made an app for myself! (Reading management app)
I made a gender selection column with enum
I made an Android app for MiRm service
I made a rock-paper-scissors game in Java (CLI)
I made a Docker container to run Maven
I made a Ruby extension library in C
[Rails] I made a draft function using enum
I made a LINE bot with Rails + heroku
A collection of RSpecs that I used frequently
I made a portfolio with Ruby On Rails
[Ruby] I want to make a program that displays today's day of the week!
I made StringUtils.isBlank
I made a lock pattern using the volume key with the Android app. Fragment edition
I made a Docker image of SDAPS for Japanese
I made a simple calculation problem game in Java
Create a docker image that runs a simple Java app
A simple CRUD app made with Nuxt / Laravel (Docker)
I made a check tool for the release module
I made a method to ask for Premium Friday
[Ruby] I made a crawler with anemone and nokogiri.
I made a Restful server and client in Spring.
SwiftUI --App development I tried arranging Views like that.
[Rails] Volume that displays favorites and a list of favorites
I tried OCR processing a PDF file with Java
I made a library for displaying tutorials on Android.
I made an Android application that GETs with HTTP