0

I want to overlay pencil kit canvases automatically on PDFView with the new PDFKit OverlayProvider Protocol in iPad OS 16. I added PKCanvas view as a subview of OverlayView, which is UIView, for PDFKit. I succeed in displaying and deleting overlay views based on the OverlayViewProvider protocol. Setup the pdfview in overlay provider

The canvases are displayed as it supposed to be, however, the pencil interaction is not activated. Instead, only the PDF UI scroll view gesture is activated. Should I drop PDF views' gestures?

PDFView for Swift UI

struct PDFKitViewRepresentable: UIViewRepresentable {
    let pdfDocument: PDFDocument
    let pdfView:PDFView
    
    
    init(showing pdfDoc: PDFDocument, pdfView:PDFView) {
        self.pdfDocument = pdfDoc
        self.pdfView = pdfView
    }
    
    func makeUIView(context: Context) -> PDFView {
        
        pdfView.displayDirection = .vertical
        pdfView.displayMode = .singlePageContinuous
        pdfView.usePageViewController(true)
        pdfView.pageBreakMargins = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        pdfView.autoScales = false
        
        pdfView.delegate = context.coordinator
        pdfView.pageOverlayViewProvider = context.coordinator
        pdfView.backgroundColor = UIColor(white: 0.04, alpha: 0.2)
        
        return pdfView
    }
    
    func updateUIView(_ pdfView: PDFView, context: Context) {
        pdfView.document = pdfDocument
    }
    
    func makeCoordinator()-> Coordinator {
        Coordinator()
    }
}

Coordinator code

class Coordinator: NSObject, PDFPageOverlayViewProvider, PDFViewDelegate, PDFDocumentDelegate, UIGestureRecognizerDelegate, PKCanvasViewDelegate, PKToolPickerObserver {
    
    var pageToViewMapping = [PDFPage: CustomUIView]()
    
    func pdfView(_ view: PDFView, overlayViewFor page: PDFPage) -> UIView? {
        var resultView:CustomUIView  = CustomUIView()
        
        if let overlayView = pageToViewMapping[page] {

        var canvas = overlayView.viewWithTag((Int(page.label!)!))
            canvas?.becomeFirstResponder()
            resultView = overlayView
        } else {
            let toolPicker = PKToolPicker.init()
            var canvasView = PKCanvasView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
            
            resultView.backgroundColor = UIColor.red.withAlphaComponent(0.1)
            canvasView.drawingPolicy = .anyInput

            canvasView.backgroundColor = .yellow.withAlphaComponent(0.2)

            resultView.frame = page.bounds(for: .mediaBox)

            toolPicker.addObserver(canvasView)
            toolPicker.setVisible(true, forFirstResponder: canvasView)
            canvasView.delegate = resultView
            canvasView.becomeFirstResponder()            
            canvasView.tag = Int(page.label!)!
            resultView.addSubview(canvasView)
            pageToViewMapping[page] = resultView
        }
        
        let page = MyPDFPage(page:page)
        return resultView
    }
    
    func pdfView(_ pdfView: PDFView, willDisplayOverlayView overlayView: UIView, for page: PDFPage){                
    // Overlay view will display
    }
    
    func pdfView(_ pdfView: PDFView, willEndDisplayingOverlayView overlayView: UIView, for page: PDFPage){
    // Overlay view would be disappear
    }
    
}


In the 2022 WWDC PDFKit video - https://developer.apple.com/videos/play/wwdc2022/10089/ - it would be achievable with less than 30 lines of code. So I use the code snippet and check the basic mechanism. But can not draw on canvas.

Carl.H.L
  • 1
  • 1
  • https://stackoverflow.com/questions/73960885/pdfkit-pdfpageoverlayviewprovider-with-pkcanvasview-is-not-forwarding-touch-ev Looks like the same issue. – Carl.H.L Dec 20 '22 at 05:30
  • Additionally, PDFView should follow those conditions pdfView.displayMode = .singlePageContinuous pdfView.usePageViewController(false) – Carl.H.L Dec 20 '22 at 05:43

2 Answers2

0

The reason why drawing gestures and scrolling gestures are having conflict was configuration of PDF View.

pdfView.displayMode = .singlePageContinuous pdfView.usePageViewController(false)

Then you should set isUserInteractionEnabled as true on overlay view install.

See PDFKit - PDFPageOverlayViewProvider with PKCanvasView is not forwarding Touch events - WWDC22 Session 10089

Carl.H.L
  • 1
  • 1
0

You need to also set isInMarkupMode on the PDFView instance to true, so it changes how hit testing works.

Majd Taby
  • 1,340
  • 1
  • 11
  • 15