skip to Main Content

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.

2

Answers


  1. Chosen as BEST ANSWER

    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


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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search