728x90
반응형

 

이전 글을 통해 PDFKit을 사용하여 단일, 다중 PDF 파일을 표시 하였습니다.

https://gigas-blog.tistory.com/262

 

[Swift] PDFKit 사용하기 #2 다중 PDF

이전글에서 PDFKit을 사용하여 간단하게 단일 PDF를 표시하는 앱을 만들어 봤습니다. 이번글에서는 여러 PDF를 하나로 병합하여 표시하는 앱을 만들어 보겠습니다. https://gigas-blog.tistory.com/261 [Swift]

gigas-blog.tistory.com

 

그런데 몇번 페이지를 보고 있는지. 전체 페이지가 몇개가 있는지 보여지는게 없네요.

 

이번 글에서는 전체페이지와 현재 페이지를 아래처럼 표시해보도록 하겠습니다.

 

아래와 같이 3개의 변수를 선언해주었습니다.

 

pageInfoContainer 는 페이지번호를 감싸주는 Container입니다.

 

currentPageLabel 은 페이지번호를 표시해주는 Label입니다.

 

timer는 일정시간 페이지번호를 표시해준뒤 PDF를 가리지 않기 위해 pageInfoContainer를 가려주는 용도로 사용합니다.

var pageInfoContainer: UIView = {
    let view = UIView()
    view.translatesAutoresizingMaskIntoConstraints = false
    view.layer.cornerRadius = 6
    view.backgroundColor = UIColor.gray
    return view
}()

var currentPageLabel: UILabel = {
    let label = UILabel()
    label.translatesAutoresizingMaskIntoConstraints = false
    label.font = UIFont.systemFont(ofSize: 12, weight: .medium)
    label.textColor = UIColor.white
    return label
}()

private var timer: Timer?

 

 

 

페이지 UI의 제약을 주기 위해 아래처럼 작성을 해주었습니다.

 

UI구성을 마쳤으니 실제 페이지번호를 보여주도록 처리해보겠습니다.

func setUpUI() {
    view.addSubview(pageInfoContainer)
    
    pageInfoContainer.addSubview(currentPageLabel)
    
    NSLayoutConstraint.activate([
        pageInfoContainer.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
        pageInfoContainer.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20),
        
        currentPageLabel.topAnchor.constraint(equalTo: pageInfoContainer.topAnchor, constant: 5),
        currentPageLabel.leadingAnchor.constraint(equalTo: pageInfoContainer.leadingAnchor, constant: 10),
        currentPageLabel.trailingAnchor.constraint(equalTo: pageInfoContainer.trailingAnchor, constant: -10),
        currentPageLabel.bottomAnchor.constraint(equalTo: pageInfoContainer.bottomAnchor, constant: -5),
    ])
}

 

 

 

PDFKit에서 지원을 하고 있으며 다양한 Notification을 지원하고 있습니다.

 

그중 PDFViewPageChanged 를 통해 페이지 상태가 변하면 handlePageChange함수로 알림을 받도록 등록합니다.

NotificationCenter.default.addObserver(self, selector: #selector(handlePageChange), name: .PDFViewPageChanged, object: nil)

 

 

 

PDFViewPageChanged 으로 등록한 Notification이 handlePageChange함수를 호출해주는데요.

 

pageIndex를 가져온 뒤 pageInfoContainer를 표시해주고 startTimer를 호출합니다.

 

startTimer에서는 타이머를 invalidate 하고 새로운 Timer를 생성해줍니다.

 

그리고 2초 뒤에 pageInfoContainer를 사라지게 해주는 whenTimerEnds함수를 호출해 줍니다.

// MARK: - PDFView PDFViewPageChanged
extension ViewController {
    @objc
    func handlePageChange() {
        view.bringSubviewToFront(currentPageLabel)
        if let currentPage: PDFPage = pdfView.currentPage,
           let pageIndex: Int = pdfView.document?.index(for: currentPage) {
            UIView.animate(withDuration: 0.5, animations: {
                self.pageInfoContainer.alpha = 1
            }) { (finished) in
                if finished {
                    self.startTimer()
                }
            }
            currentPageLabel.text = "\(pageIndex + 1) of \(pdfView.document?.pageCount ?? .zero)"
        }
    }
    
    private func startTimer() {
        timer?.invalidate()
        timer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(whenTimerEnds), userInfo: nil, repeats: false)
    }

    @objc
    func whenTimerEnds() {
        UIView.animate(withDuration: 1) {
            self.pageInfoContainer.alpha = 0
        }
    }
}

 

 

 

타이머를 사용했다면 deinit 될때 꼭 invalidate 처리를 해주어야겠죠.

deinit {
    timer?.invalidate()
}

 

 

 

이렇게 작성된 코드를 Build하면 아래처럼 페이지 이동시 현재페이지와 전체페이지를 보여주는 View를 보실 수 있습니다.

 

이로써 기본 기능에 충실한 PDFViewer를 만들어 보았습니다.

 

다양한 용도로 Custom 을 하여 더 멋진 PDFViewer를 만들어보세요.

 

 

 

 

지금까지 작성한 코드는 GitHub 를 통해 확인하실 수 있습니다.

https://github.com/bonjin-app/iOS/blob/main/PDFKitExample/PDFKitExample/ViewController.swift

 

bonjin-app/iOS

Contribute to bonjin-app/iOS development by creating an account on GitHub.

github.com

 

728x90
반응형
728x90
반응형

 

이전글에서 PDFKit을 사용하여 간단하게 단일 PDF를 표시하는 앱을 만들어 봤습니다.

 

이번글에서는 여러 PDF를 하나로 병합하여 표시하는 앱을 만들어 보겠습니다.

https://gigas-blog.tistory.com/261

 

[Swift] PDFKit #1 단일 PDF

PDFKit은 공식 문서를 보면 PDF데이터를 보여주거나 작성 및 검색을 할 수 있다고 나와있습니다. iOS 11 이상부터 사용이가능하기에 이전 버전을 지원하는 앱에서는 사용이 불가능합니다. https://devel

gigas-blog.tistory.com

 

 

 

이전처럼 함수로 미리 작성해 주겠습니다.

 

PDFDocument를 배열로 받아서 document에 insert함수를 이용하여 추가하는 방식입니다.

 

PDFDocument를 PDFPage로 변환하여 보여질 document에 insert만 하면 된다는게 정말 쉽군요.

func loadMultiplePdfView(inputDocuments: [PDFDocument]) {
    let document: PDFDocument = PDFDocument()
    for input in inputDocuments {
        for i in .zero...input.pageCount {
            if let page: PDFPage = input.page(at: i) {
                document.insert(page, at: document.pageCount)
            }
        }
    }
    
    pdfView.autoScales = true
    pdfView.displayMode = .singlePageContinuous
    pdfView.displayDirection = .vertical
    pdfView.document = document
}

 

 

 

아래 코드를 ViewDidLoad함수에 넣어서 실행해보겠습니다.

let urlStrings = ["http://www.africau.edu/images/default/sample.pdf",
                 "http://www.africau.edu/images/default/sample.pdf",
                 "http://www.africau.edu/images/default/sample.pdf"]
        
let documents = urlStrings.compactMap { (urlString) -> PDFDocument? in
    if let url = URL(string: urlString),
       let document = PDFDocument(url: url) {
        return document
    }
    return nil
}
loadMultiplePdfView(inputDocuments: documents)

 

 

 

하나의 pdf가 2개 page 를 갖고 있기 때문에 3개를 호출하여 6개의 page를 만들어서 표시 했습니다.

 

 

정말 간단하지요? PDFKit의 장점은 Custom이 가능하다는 것입니다.

 

TableView를 추가하여 좌측에 전체 페이지를 보여주는것도 가능하고, PDFView의 go 라는 함수로 특정 페이지로 스크롤을 이동시키는것도 가능합니다.

 

 

WebKit으로 PDF를 병합하려고 찾지 마시고 PDFKit을 통해서 해결해보시는게 어떨까요?

 

다양하게 본인만의 PDFViewer를 만들어보세요.

 

728x90
반응형
728x90
반응형

 

PDFKit은 공식 문서를 보면 PDF데이터를 보여주거나 작성 및 검색을 할 수 있다고 나와있습니다.

 

iOS 11 이상부터 사용이가능하기에 이전 버전을 지원하는 앱에서는 사용이 불가능합니다.

https://developer.apple.com/documentation/pdfkit/pdfdocument

 

Apple Developer Documentation

 

developer.apple.com

 

 

 

 

기존 프로젝트에 약관을 확인하려는 용도로 WebKit을 사용하여 html파일을 로드하는 방식으로 사용을 하고 있었습니다.

 

Server 에서 pdf로 보내도 WebKit에서 변환하여 잘 보여주고 있는데요.

 

PDFKit을 사용하여 다양한 방식으로 표시를 해보겠습니다.

 

 

 

새로운 xcode 프로젝트를 PDFKitExample이라는 이름으로 만들어줍니다.

 

그리고 Main.storyboard의 ViewController에 UIView를 만들어주는데 class를 'PDFView'로 연결해줍니다.

 

PDFView는 PDFKit에서 지원하는 UIView를 상속하여 만들어진 View이고 PDF파일을 보여주는 역할을 합니다.

 

 

ViewController로 돌아와 PDFKit을 import하고 조금전에 만든 PDFView 를 pdfView 와 연결합니다.

import UIKit
import PDFKit

class ViewController: UIViewController {

    @IBOutlet weak var pdfView: PDFView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
}

 

 

 

이제 pdfView에 pdf파일을 연결하는 함수를 작성해 줍니다.

 

PDFDocument라는 Parameter를 받아서 pdfView와 연결해줍니다.

 

autoScales 는 뷰의 크기가 조정되거나 회전 될 때 배율이 자동으로 변경되는 모드입니다.

true, false 로 구성되어있습니다.

 

displayMode는 문서 표시 모드 이며 기본값은 singlePageContinuous로 단일 페이지 방식입니다.

singlePage, singlePageContinuous, twoUp, twoUpContinuous 모드가 있습니다.

 

displayDirection은 vertical과 horizontal로 구성되어있고 기본값은 vertical 모드 입니다.

 

마지막으로 document라는 속성에 PDFDocument를 연결하면 됩니다.

func loadPdfView(document: PDFDocument) {
        pdfView.autoScales = true
        pdfView.displayMode = .singlePageContinuous
        pdfView.displayDirection = .vertical
        pdfView.document = document
    }

 

 

 

url을 받아서 PDFDocument로 변환하여 loadPdfView함수를 호출하도록 처리 했습니다.

 

local방식과 web방식을 선택하여 사용하면 되고, 아래 코드를 ViewDidLoad 함수에 넣어서 실행해보겠습니다.

// local Sample Pdf
// let url = Bundle.main.url(forResource: "sample", withExtension: "pdf")

// web Sample Pdf
let url = "http://www.africau.edu/images/default/sample.pdf"

if let url = URL(string: urlString),
	let document = PDFDocument(url: url) {
	loadPdfView(document: document)
}

 

 

 

WebView처럼 pdf파일을 잘 불러온것을 확인할 수 있습니다.

 

 

위처럼 간단하게 하나의 pdf파일을 로드해서 표시를 해봤습니다.

 

다음글에서는 pdf파일이 여러개 있을때 하나로 표시하는 방법을 알아보도록 하겠습니다.

 

728x90
반응형

+ Recent posts