2

In iOS 11, I have a PDFView controller implementation that allows to annotate a PDF, and one of those annotation if free-form drawing using PDFAnnotationSubtypeInk

        let page : PDFPage = ...
        let points : [CGPoint] = ...
        let path = UIBezierPath()
        for x in 0..<points.count {
            let point = self.pdfView.convert(points[x], to: page)
            if x == 0 {
                path.move(to: point)
            }else{
                path.addLine(to: point)
            }
        }

        let border = PDFBorder()
        border.style = .solid
        border.lineWidth = 2.0

        let drawAnnotation = PDFAnnotation(bounds: page.bounds(for: .mediaBox), forType: .ink, withProperties: nil)
        drawAnnotation.backgroundColor = .yellow
        drawAnnotation.interiorColor = .yellow
        drawAnnotation.fontColor = .yellow
        drawAnnotation.color = .yellow
        drawAnnotation.border = border
        drawAnnotation.add(path)
        page.addAnnotation(drawAnnotation)

When I call the persistence code

    if let path = self.pdfDocumentPath, let document = self.pdfDocument {
        if !document.write(toFile: path){
            NSLog("Failed to save PDF")
        }
    }

Everything works in theory, the PDF is saved to disk... But on the next-reload from disk, my annotation is nowhere to be seen. Other types of annotations are saved correctly (i.e. Text and Highlight)

It looks like the UIBezierPaths never makes it back from Disk. No UIBezierPath is to be found in the reloaded PDFAnnotation

Am I doing something wrong? Am I missing something?

PS: I am sorry for Ruby devs that are looking for questions/answers on the Ruby Package known as PDFKit... iOS also have a package named PDFKit since iOS 11... Sorry for any confusion.

McDonal_11
  • 3,935
  • 6
  • 24
  • 55
Claude Houle
  • 41,064
  • 8
  • 33
  • 42

2 Answers2

2

I hacked my way around the problem. The annotation get saved, but the UIBezierPath does not (and all it's points)

So when I write the PDF back to disk, I go through all the pages, and all annotations, and find those with UIBezierPath, and serialize the CGPoints into JSON into the PDFAnnotation content property.

When reloading the same PDF, I do the exact same thing, which is go through all the pages, and find .ink annotation, deserialize the points, and add the UIBezierPath back on the annotation.

Claude Houle
  • 41,064
  • 8
  • 33
  • 42
  • Could you please explain how does your serialization/deserialization work? How do you get the points of a path and how do you build a path from an array of points? – lhmgrassi Jun 25 '19 at 21:23
2

Apple fixed this bug in iOS 12. PDFAnnotation.paths is filled correctly.

Starting with some version between 11.2 - 11.4 (I do not have the opportunity to verify, but it does not work exactly in 11.1 and works in 11.4+) you can use PDFAnnotation method drawWithBox:inContext: for rendering ink annotation correctly.

Attention, in iOS 12.0 Apple broke PDFAnnotation.color (alpha is always equal 1 after save-reload PDFDocument from disk). Can be repaired by drawing an annotation through the context with method above.

K. Dmitry
  • 33
  • 7