PDFView with PKCanvasView drawingGestureRecognizer on iOS14

1.3k Views Asked by At

Minimum code to add a PKCanvasView to PDFView. The PKCanvasView displays properly if the PKDrawing is set. However on iOS14, the drawingGestureRecognizer does not fire. Works on iOS13

import UIKit
import PDFKit
import PencilKit

class ViewController: UIViewController {

    
    @IBOutlet var pdfView: PDFView!
    var scrollView : UIScrollView!
    var pkView : PKCanvasView!
    var docView : UIView!
    var drawing : PKDrawing!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        setupPDF()
        setupPencil()
    }
    
    func setupPDF() {
        let fileURL = Bundle.main.url(forResource: "test", withExtension: "pdf")!
        let pdfDocument = PDFDocument(url: fileURL)
        pdfView.document = pdfDocument
    }
    
    func setupPencil() {
        for scroll in self.allSubViews(in: self.pdfView, ofType: UIScrollView.self) {
            self.scrollView = scroll
            break
        }
        
        for view in self.allSubViews(in: self.scrollView, ofType: UIView.self) {
            if "\(view)".starts(with: "<PDFDocumentView: ") {
                self.docView = view
                break
            }
        }

        self.pkView = PKCanvasView(frame: CGRect(origin: CGPoint.zero, size: self.docView.bounds.size))
        self.pkView.isOpaque = false
        self.pkView.backgroundColor = .clear
        
        self.docView.addSubview(self.pkView)
        self.pkView.tool = PKInkingTool(.pen, color: .black, width:0.4)
        
        self.pkView.overrideUserInterfaceStyle = .light
        
        if let _drawing = self.drawing {
            self.pkView.drawing = _drawing
        }
        
        self.scrollView.panGestureRecognizer.minimumNumberOfTouches = 2
        self.scrollView.addGestureRecognizer(self.pkView.drawingGestureRecognizer)
    }


    func allSubViews<T: UIView>(in view:UIView, ofType type: T.Type) -> [T] {
        var all: [T] = []
        func getSubview(view: UIView) {
            if let aView = view as? T {
                all.append(aView)
            }
            guard view.subviews.count > 0 else { return }
            view.subviews.forEach{ getSubview(view: $0) }
        }
        getSubview(view: view)
        return all
    }
}

FYI, the pages are rendered dynamically and can be added and removed from the hierarchy. If you're using this code, you need to bringSubviewToFront when pages change.

0

There are 0 best solutions below