iOS16中PDFKit的PDFPageOverlayViewProvider绑定PKCanvasView触控事件未转发求助
解决PDFView叠加PKCanvasView的Apple Pencil触摸事件问题
核心思路
问题根源是PDFDocumentView的触摸响应优先级高于PKCanvasView,导致Apple Pencil的触摸被拦截。我们需要调整事件响应链,让Pencil触摸优先传递给PKCanvasView,同时保留PDFView的滚动、拖放等常规交互。
具体实现方案
1. 自定义PKCanvasView子类,针对性拦截Pencil触摸
创建PencilPriorityCanvasView,重写触摸相关方法,只对Apple Pencil的触摸事件返回自身,其他事件交给父视图处理:
import UIKit import PencilKit class PencilPriorityCanvasView: PKCanvasView { override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { // 仅响应Apple Pencil的触摸 guard let touch = event?.touches(for: self)?.first, touch.type == .pencil else { return false } return super.point(inside: point, with: event) } override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { let hitView = super.hitTest(point, with: event) // 若为Pencil触摸,确保返回自身 if let touch = event?.touches(for: self)?.first, touch.type == .pencil { return hitView == self ? self : nil } // 其他事件交给父视图,不拦截 return nil } }
2. 实现PDFPageOverlayViewProvider时使用自定义Canvas
在提供overlay视图时,替换为上面的自定义类,并确保交互开启:
class PDFOverlayProvider: NSObject, PDFPageOverlayViewProvider { func pdfView(_ pdfView: PDFView, overlayViewFor page: PDFPage) -> UIView? { let canvasView = PencilPriorityCanvasView(frame: .zero) canvasView.drawingPolicy = .anyInput canvasView.isUserInteractionEnabled = true // 用tag绑定PDF页面,方便后续坐标转换 canvasView.tag = page.hashValue return canvasView } func pdfView(_ pdfView: PDFView, willDisplayOverlayView overlayView: UIView, for page: PDFPage) { // 让overlay尺寸匹配PDF页面 overlayView.frame = pdfView.convert(page.bounds(for: .mediaBox), to: pdfView) } }
3. 优化PDFView的手势设置(可选)
如果PDFView的滚动、缩放手势仍有冲突,可调整手势属性避免拦截:
pdfView.isUserInteractionEnabled = true // 确保滚动、缩放手势不阻断触摸传递 pdfView.scrollView.panGestureRecognizer.cancelsTouchesInView = false pdfView.scrollView.pinchGestureRecognizer.cancelsTouchesInView = false
关键原理
通过自定义Canvas的hitTest和point(inside:)方法,精准过滤出Apple Pencil的触摸事件并响应,其他触摸(比如手指滚动)会穿透到下层的PDFDocumentView,既保证了绘图功能,又不影响PDFView的常规操作。
内容的提问来源于stack exchange,提问作者larsschwegmann
相关产品推荐
相关产品推荐

