I want to allow the user to draw on an iOS 11 PDFKit document viewed in a PDFView. The drawing should ultimately be embedded inside the PDF.
The latter I have solved by
I've done this by creating a new view class (eg Annotate View) and putting on top of the PDFView when the user is annotating.
This view uses it's default touchesBegan/touchesMoved/touchesEnded methods to create a bezier path following the gesture. Once the touch has ended, my view then saves it as an annotation on the pdf.
Note: you would need a way for the user to decide if they were in an annotating state.
For my main class
class MyViewController : UIViewController, PDFViewDelegate, VCDelegate {
var pdfView: PDFView?
var touchView: AnnotateView?
override func loadView() {
touchView = AnnotateView(frame: CGRect(x: 0, y: 0, width: 375, height: 600))
touchView?.backgroundColor = .clear
touchView?.delegate = self
view.addSubview(touchView!)
}
func addAnnotation(_ annotation: PDFAnnotation) {
print("Anotation added")
pdfView?.document?.page(at: 0)?.addAnnotation(annotation)
}
}
My annotation view
class AnnotateView: UIView {
var path: UIBezierPath?
var delegate: VCDelegate?
override func touchesBegan(_ touches: Set, with event: UIEvent?) {
// Initialize a new path for the user gesture
path = UIBezierPath()
path?.lineWidth = 4.0
var touch: UITouch = touches.first!
path?.move(to: touch.location(in: self))
}
override func touchesMoved(_ touches: Set, with event: UIEvent?) {
// Add new points to the path
let touch: UITouch = touches.first!
path?.addLine(to: touch.location(in: self))
self.setNeedsDisplay()
}
override func touchesEnded(_ touches: Set, with event: UIEvent?) {
let touch = touches.first
path?.addLine(to: touch!.location(in: self))
self.setNeedsDisplay()
let annotation = PDFAnnotation(bounds: self.bounds, forType: .ink, withProperties: nil)
annotation.add(self.path!)
delegate?.addAnnotation(annotation)
}
override func touchesCancelled(_ touches: Set, with event: UIEvent?) {
self.touchesEnded(touches, with: event)
}
override func draw(_ rect: CGRect) {
// Draw the path
path?.stroke()
}
override init(frame: CGRect) {
super.init(frame: frame)
self.isMultipleTouchEnabled = false
}
}