Introduction to Annotations

PSPDFKit supports all common annotation types:

These are standard annotations (as defined in the PDF Reference) that can be read and written by many apps, like Adobe Acrobat or even Apple’s Preview.app. Most of these annotation types can also be written back, with the exception of rich media/video, file, and widget. (See also: What Are Annotations?)

Working with Annotations in Code

You can work with all supported annotations not only in our UI but also in code. We have APIs for various operations, including getting, setting, modifying, and removing annotations.

To get all annotations on a certain document page, you can call annotationsForPage(at:type:):

1
2
// Get all annotations on the first page.
let annotations = document.annotationsForPage(at: 0, type: .all)
Copy
1
2
// Get all annotations on the first page.
NSArray<__kindof PSPDFAnnotation *> *annotations = [document annotationsForPageAtIndex:0 type:PSPDFAnnotationTypeAll]

Creating Annotations

You can instantiate annotations with their corresponding classes, which are all subclasses of the base Annotation class:

Copy
1
2
3
4
5
6
// Create a free text annotation.
let freeTextAnnotation = FreeTextAnnotation()
freeTextAnnotation.contents = "This is a free text annotation."
freeTextAnnotation.fontSize = 20
freeTextAnnotation.boundingBox = CGRect(x: 200, y: 200, width: 200, height: 200)
freeTextAnnotation.pageIndex = 0
Copy
1
2
3
4
5
6
// Create a free text annotation.
PSPDFFreeTextAnnotation *freeTextAnnotation = [[PSPDFFreeTextAnnotation alloc] init];
freeTextAnnotation.contents = @"This is a free text annotation.";
freeTextAnnotation.fontSize = 20.f;
freeTextAnnotation.boundingBox = CGRectMake(200.f, 200.f, 200.f, 200.f);
freeTextAnnotation.pageIndex = 0;

For a more detailed guide, please refer to Programmatically Creating Annotations.

Adding and Removing Annotations

To add annotations on a document page, you can use add(annotations:options:) on Document. To remove annotations on the document, you can use remove(annotations:options:):

Copy
1
2
3
4
5
// Add an annotation to a document.
document.add(annotations: [freeTextAnnotation])

// Remove an annotation from a document.
document.remove(annotations: [freeTextAnnotation])
Copy
1
2
3
4
5
// Add an annotation to a document.
[document addAnnotations:@[freeTextAnnotation] options:nil];

// Remove an annotation from a document.
[document removeAnnotations:@[freeTextAnnotation] options:nil];

You can also remove all annotations from a document using allAnnotations(of:) and remove(annotations:options:). You usually don’t want to remove links and form elements, which are also annotations. These annotation types can be excluded, as seen in the code snippet below:

Copy
1
2
3
4
5
6
7
var annotationTypes = Annotation.Kind.all
annotationTypes.remove([.link, .widget])
let allAnnotationsDictionary = document.allAnnotations(of: annotationTypes)
let allAnnotations = allAnnotationsDictionary.flatMap { key, value in
    return value
}
document.remove(annotations: allAnnotations)
Copy
1
2
3
4
5
6
7
NSDictionary *allAnnotationsDictionary = [document allAnnotationsOfType:PSPDFAnnotationTypeAll & ~(PSPDFAnnotationTypeLink|PSPDFAnnotationTypeWidget)];

NSMutableArray *allAnnotations = [NSMutableArray array];
[allAnnotationsDictionary enumerateKeysAndObjectsUsingBlock: ^(NSNumber *key, NSArray *value, BOOL *stop) {
    [allAnnotations addObjectsFromArray:value];
}];
[document removeAnnotations:allAnnotations options:nil];

Saving Annotations with PSPDFKit

ℹ️ Note: Annotations can only be written back into a PDF if the file is writeable. The default location (App Bundle) is read-only.

Optionally, and as a fallback, annotations can also be written as external files. This is the default behavior if a PDF is read-only and can be customized by changing annotationSaveMode. The valid options are:

For more information, please see the Annotation-Saving Mechanism guide.

Handling Annotations with PSPDFKit

Annotations are handled by the AnnotationManager class, an instance of which is managed by a PDFDocumentProvider. A Document has one or more PDFDocumentProviders, depending on the amount of PDF files it contains (usually just one).

Subclass PDFContainerAnnotationProvider to implement a custom annotation provider, as this class offers efficient undo/redo which otherwise is almost impossible to replicate unless you understand the PSPDFKit internals extremely well. If you want to change AnnotationManager across the application, the best way to do this is to use overrideClass(_:with:) on Document.

In case you’re customizing the default UI that ships with PSPDFKit, make sure to add the annotationButtonItem to the toolbar to be able to show the annotation toolbar.

The preferred way to customize annotation handling is to implement a custom AnnotationProvider subclass. We provide a subclass (PDFContainerAnnotationProvider) that is a good base to build upon.

Furthermore, with PDFConfiguration’s editableAnnotationTypes property, you can customize which annotations can be edited. Set this property to nil to completely disable annotation editing/creation.

ℹ️ Note: Be aware that a document can also disable annotation editing and creation altogether via document permissions. If editableAnnotationTypes is not nil or empty, but you can’t interact with existing annotations or create new ones, the document might not have the relevant permissions granted.

Checking If a Document Contains Annotations

When calling allAnnotations(of:), PSPDFKit will return all annotations of the specified type(s). To check if a document contains annotations, you will likely want to check all annotations except links or widgets, like so:

Copy
1
2
3
var annotationTypes = Annotation.Kind.all
annotationTypes.remove([.link, .widget])
let allAnnotationsDictionary = document.allAnnotations(of: annotationTypes)
Copy
1
NSDictionary *allAnnotationsDictionary = [document allAnnotationsOfType:PSPDFAnnotationTypeAll & ~(PSPDFAnnotationTypeLink|PSPDFAnnotationTypeWidget)];

This returns all annotations, excluding link and widget annotations. Widget annotations include simple buttons and all form element types. allAnnotations(of:) returns a dictionary where the key is the page number and the value is an array containing all annotations on that page, so you need to check if any of those arrays have any annotations.

PSPDFCatalog contains many examples of working with annotations, so be sure to check them out.

Uniquely Identifying Annotations

While the name property of an annotation is defined in the PDF spec as optional, PSPDFKit automatically sets name to a unique identifier (UUID) each time an annotation is created.

Storing Custom Data in Annotations

You can persistently store custom data on a per-annotation basis using Annotation’s customData property. More information about customData is available in the corresponding guide.