9

Can the text (i.e. contents) of a FreeText annotation be changed in PDFKit without deleting an annotation / building a new annotation?

The following snippet does not change an annotation's contents when viewing in a PDFView:

let url = Bundle.main.url(forResource: "Test", withExtension: "pdf")!
let document = PDFDocument(url: url)!

for index in 0..<document.pageCount {
    let page: PDFPage = document.page(at: index)!
    let annotations = page.annotations
    for annotation in annotations {
        annotation.contents = "[REPLACED]"
    }
}
mainPDFView.document = document

This works - but requires replacing an annotation (and thus having to copy over all the other details of the annotation):

let url = Bundle.main.url(forResource: "Test", withExtension: "pdf")!
let document = PDFDocument(url: url)!

for index in 0..<document.pageCount {
    let page: PDFPage = document.page(at: index)!
    let annotations = page.annotations
    for annotation in annotations {
        print(annotation)
        page.removeAnnotation(annotation)
        let replacement = PDFAnnotation(bounds: annotation.bounds,
                                        forType: .freeText,
                                        withProperties: nil)

        replacement.contents = "[REPLACED]"
        page.addAnnotation(replacement)
    }
}

mainPDFView.document = document

Note: adding / removing the same annotation also does not help.

Kevin Sylvestre
  • 37,288
  • 33
  • 152
  • 232

2 Answers2

2

I suggest you iterate over the annotations array using a classic for loop and find the index of the annotation you want to modify, after that subscripting the array should modify the annotation "in place".

Here's an example which modifies all annotations:

let url = Bundle.main.url(forResource: "Test", withExtension: "pdf")!
let document = PDFDocument(url: url)!

for index1 in 0..<document.pageCount {
    let page: PDFPage = document.page(at: index)!
    let annotations = page.annotations
    for index2 in 0..<annotations.count {
        annotations[index2].contents = "[REPLACED]"
    }
}

Have a read about mutating arrays: http://kelan.io/2016/mutating-arrays-of-structs-in-swift/

Hope it helps, cheers!

LE: It's a bug actually, see this one: iOS 11 PDFKit not updating annotation position

Maybe Apple will find a way to update the PDFView on screen when you change the contents of an annotation SOON..

Mihai Erős
  • 1,129
  • 1
  • 11
  • 18
  • I don't think this helps. Annotation is not a value type (Class). I also think the compiler will warn something like 'Cannot assign to 'let' constant property...' or something if that is the case... – Kevin Sylvestre Jul 26 '18 at 23:39
  • I updated my answer, because I started to try your exact case as you we're right. Tested your and it works fine - in terms of mutating the contents property of the PDFAnnotation objects - your problem is actually that your PDFView (on screen) doesn't get refreshed and you don't see your changes, I get it now, but the changes happened.. This is a bug, plain and simple in my opinion. – Mihai Erős Jul 27 '18 at 06:45
  • I don't think your other point is the issue either. I am not adding the document to a PDFView until I have changed the annotations. – Kevin Sylvestre Jul 27 '18 at 18:11
  • What's your question again? – Mihai Erős Jul 27 '18 at 22:41
  • I asked if the text of a `FreeText` annotation can be changed in PDFKit without deleting the annotation then building a new annotation. The original question has all the details. – Kevin Sylvestre Jul 28 '18 at 07:09
  • And my answer basically says YES you can. – Mihai Erős Jul 30 '18 at 09:27
  • Don't know how it doesn't work for you, cause it does for me. – Mihai Erős Jul 31 '18 at 12:37
  • 2
    Note: it looks like this is a bug with the SDK confirmed by Pranav. Awarding the bounty to make sure it doesn't go to waste... – Kevin Sylvestre Aug 03 '18 at 17:35
0

Have you tried calling pdfView.annotationsChanged(on: pdfPage) after updating the annotation's text?

crcalin
  • 979
  • 6
  • 13