스토리 보드에 UIView를 올리고 class 명을 PDFView로 설정하면 된다.

PDF 로드 및 페이지 표시 기능만 생성했다.

import UIKit
import PDFKit

extension PDFKitViewController: PDFViewDelegate {
    
}

class PDFKitViewController: UIViewController {
    
    @IBOutlet weak var pdfView: PDFView!
    
    var pageInfoContainer: UIView = {
       let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.layer.cornerRadius = 6.0
        view.backgroundColor = .gray
        return view
    }()
    
    var currentPageLabel: UILabel = {
       let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.font = UIFont.systemFont(ofSize: 12, weight: .medium)
        label.textColor = .white
        return label
    }()
    
    private var timer: Timer?
    
    deinit {
        timer?.invalidate()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.pdfView.delegate = self
        
        // https://www.tutorialspoint.com/swift/swift_tutorial.pdf
        // http://www.africau.edu/images/default/sample.pdf
        let url = "https://www.tutorialspoint.com/swift/swift_tutorial.pdf"
        
        DispatchQueue.global().async { [weak self] in
            if let url = URL(string: url) {
                if let document = PDFDocument(url: url) {
                    self?.loadPdfView(document: document)
                }
            }
        }
        
        setupUI()
        addObservers()
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
    }
    
    // 현재 Page UI
    func setupUI() {
        view.addSubview(pageInfoContainer)
        
        pageInfoContainer.addSubview(currentPageLabel)
        
        NSLayoutConstraint.activate([
            pageInfoContainer.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
            pageInfoContainer.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, 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)
        ])
    }
    
    func loadPdfView(document: PDFDocument) {
        DispatchQueue.main.async { [weak self] in
            guard let `self` = self else { return }
            self.pdfView.autoScales = true
            self.pdfView.displayMode = .singlePageContinuous
            self.pdfView.displayDirection = .vertical
            self.pdfView.document = document
        }
    }
    
    
    func addObservers() {
        NotificationCenter.default.addObserver(self, selector: #selector(handlePageChange), name: .PDFViewPageChanged, object: nil)
    }
    
    @objc func handlePageChange() {
        view.bringSubviewToFront(pageInfoContainer)
        
        if let currentPage: PDFPage = pdfView.currentPage {
            let pageIndex = pdfView.document?.index(for: currentPage)
            UIView.animate(withDuration: 0.5, animations: {
                self.pageInfoContainer.alpha = 1.0
            }) { (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(whenTimeEnds), userInfo: nil, repeats: false)
    }
    
    @objc func whenTimeEnds() {
        UIView.animate(withDuration: 1) {
            self.pageInfoContainer.alpha = 0.0
        }
    }
}

+ Recent posts