Programmatically Creating Annotations

You can programmatically create link, highlight, free text, ink or note annotations just like any other types of supported annotations, but it's easy to get this wrong.

To create annotations programmatically you roughly follow these steps:

  1. Create the annotation by initializing it and optionally settings it’s contents.
  2. Define where you want to put the annotation in the document. You do this by setting the boundingBox property of the annotation object.
  3. Optionally customize the appearance of the annotation.
  4. Add the annotation to the document with addAnnotations:options:.

For a list of supported annotations please see Introduction to Annotations.

Customize the Appearance

There are a few different ways to customize the apperance of annotations. You can set the properties on PSPDFAnnotation or any of its subclasses to style the annotation to your liking.

Use PSPDFAnnotationStyleManager to get the last used styles the user changed in the UI for a specific annotation type and apply it to a new annotation.

Copy
1
2
3
let annotation = // Create a PSPDFAnnotation (subclass) instance
let style = PSPDFKit.sharedInstance.styleManager.lastUsedStyle(forKey: annotation.typeString)
style?.apply(to: annotation)
Copy
1
2
3
PSPDFAnnotation *annotation = // Create a PSPDFAnnotation (subclass) instance
PSPDFAnnotationStyle *style = [PSPDFKit.sharedInstance.styleManager lastUsedStyleForKey:annotation.typeString];
[style applyStyleToAnnotation:annotation];

Examples for Creating Some Annotation Types

The PSPDFCatalog contains many examples for programmatically adding annotations, be sure to check them out in AddAnnotationsProgrammaticallyExamples.

Link Annotations

PSPDFLinkAnnotation API

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Create PSPDFDocument
let document = PSPDFDocument(url: documentURL)

// Create a new link annotation and set it's URL
let linkAnnotation = PSPDFLinkAnnotation(url: URL(string: "https://pspdfkit.com")!)

// Define where you want to place the annotation in the document
let boundingBox = CGRect(x: 200, y: 400, width: 50, height: 300)
linkAnnotation.boundingBox = boundingBox

// Customize the link annotation's appearance
PSPDFLinkAnnotationView.appearance().borderColor = .blue

// Add the newly created annotation to the document
document.add([linkAnnotation])
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Create PSPDFDocument
PSPDFDocument *document = [[PSPDFDocument alloc] initWithURL:documentURL];

// Create a new link annotation and set it's URL
PSPDFLinkAnnotation *linkAnnotation = [[PSPDFLinkAnnotation alloc] initWithURL:[NSURL URLWithString:@“https://pspdfkit.com”]];

// Define where you want to place the annotation in the document
CGRect boundingBox = { .origin.x = 200.f, .origin.y = 400.f, .size.height = 50.f, .size.width = 300.f };
linkAnnotation.boundingBox = boundingBox;

// Customize the link annotation's appearance
[[PSPDFLinkAnnotationView appearance] setBorderColor:[UIColor blueColor]];

// Add the newly created annotation to the document
[document addAnnotations:@[linkAnnotation] options:nil];

Highlight Annotations

PSPDFHighlightAnnotation API

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Create PSPDFDocument
let document = PSPDFDocument(url: documentURL)

// Create a new highlight annotation
let highlightAnnotation = PSPDFHighlightAnnotation()

// Define where you want to place the annotation in the document
let boundingBox = CGRect(x: 200, y: 400, width: 50, height: 300)
highlightAnnotation.boundingBox = boundingBox

// For highlight annotations you also need to set the rects array accordingly
highlightAnnotation.rects = [NSValue(cgRect: boundingBox)]

// Add the newly created annotation to the document
document.add([highlightAnnotation])
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Create PSPDFDocument
PSPDFDocument *document = [[PSPDFDocument alloc] initWithURL:documentURL];

// Create a new highlight annotation
PSPDFHighlightAnnotation *highlightAnnotation = [[PSPDFHighlightAnnotation alloc] init];

// Define where you want to place the annotation it in the document
CGRect boundingBox = { .origin.x = 200.f, .origin.y = 400.f, .size.height = 50.f, .size.width = 300.f };
highlightAnnotation.boundingBox = boundingBox;

// For highlight annotations you also need to set the rects array accordingly
highlightAnnotation.rects = @[[NSValue valueWithCGRect:boundingBox]];

// Add the newly created annotation to the document
[document addAnnotations:@[highlightAnnotation] options:nil];

Free Text Annotations

PSPDFFreeTextAnnotation API

Copy
1
2
3
4
5
6
7
8
9
10
11
12
// Create PSPDFDocument
let document = PSPDFDocument(url: documentURL)

// Create a new free text annotation by defining it’s contents
let freeTextAnnotation = PSPDFFreeTextAnnotation(contents: "PSPDFKit")

// Define where you want to place the annotation in the document
let boundingBox = CGRect(x: 200, y: 400, width: 50, height: 300)
freeTextAnnotation.boundingBox = boundingBox

// Add the newly created annotation to the document
document.add([freeTextAnnotation])
Copy
1
2
3
4
5
6
7
8
9
10
11
12
// Create PSPDFDocument
PSPDFDocument *document = [[PSPDFDocument alloc] initWithURL:documentURL];

// Create a new free text annotation by defining it’s contents
PSPDFFreeTextAnnotation *freeTextAnnotation = [[PSPDFFreeTextAnnotation alloc] initWithContents:@"PSPDFKit"];

// Define where you want to place the annotation it in the document
CGRect boundingBox = { .origin.x = 200.f, .origin.y = 400.f, .size.height = 50.f, .size.width = 300.f };
freeTextAnnotation.boundingBox = boundingBox;

// Add the newly created annotation to the document
[document addAnnotations:@[freeTextAnnotation] options:nil];

Ink Annotations

PSPDFInkAnnotation API

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Create PSPDFDocument
let document = PSPDFDocument(url: documentURL)

// Create line by defining a start and end point
let startPoint = CGPoint(x: 200, y: 400)
let endPoint = CGPoint(x: 400, y: 600)

let lines = [[NSValue(cgPoint: startPoint), NSValue(cgPoint: endPoint)]]

// Create a new ink annotation by setting lines
let inkAnnotation = PSPDFInkAnnotation(lines: lines)

// No need to set boundingBox for ink annotations if lines are defined

// Customize line color (the related property fillColor changes the background color of the whole bounding box)
inkAnnotation.borderColor = .blue

// Customize line width
inkAnnotation.lineWidth = 5

// Add the newly created annotation to the document
document.add([inkAnnotation])
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Create PSPDFDocument
PSPDFDocument *document = [[PSPDFDocument alloc] initWithURL:documentURL];

// Create line by defining a start and end point
CGPoint startPoint = { .x = 200.f, .y = 400.f };
CGPoint endPoint = { .x = 400.f, .y = 600.f };

NSArray *lines = @[@[[NSValue valueWithCGPoint:startPoint], [NSValue valueWithCGPoint:endPoint]]];

// Create a new ink annotation by setting lines
PSPDFInkAnnotation *inkAnnotation = [[PSPDFInkAnnotation alloc] initWithLines:lines];

// No need to set boundingBox for ink annotations if lines are defined

// Customize line color (the related property fillColor changes the background color of the whole bounding box)
inkAnnotation.borderColor = [UIColor blueColor];

// Customize line width
inkAnnotation.lineWidth = 5.f;

// Add the newly created annotation to the document
[document addAnnotations:@[inkAnnotation] options:nil];

Note Annotations

PSPDFNoteAnnotation API

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
// Create PSPDFDocument
let document = PSPDFDocument(url: documentURL)

// Create a new note annotation and set its contents
let noteAnnotation = PSPDFNoteAnnotation(contents: "PSPDFKit")

// Note annotations are rendered as fixed size; much like how Adobe Acrobat renders them
// PSPDFKit will always render note annotations at a fixed size of 32x32pt. We recommend that you set the boundingBox to the same value
let boundingBox = CGRect(x: 200, y: 400, width: 32, height: 32)
noteAnnotation.boundingBox = boundingBox

// Add the newly created annotation to the document
document.add([noteAnnotation])
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
// Create PSPDFDocument
PSPDFDocument *document = [[PSPDFDocument alloc] initWithURL:documentURL];

// Create a new note annotation and set its contents
PSPDFNoteAnnotation *noteAnnotation = [[PSPDFNoteAnnotation alloc] initWithContents:@"PSPDFKit"];

// Note annotations are rendered as fixed size; much like how Adobe Acrobat renders them
// PSPDFKit will always render note annotations at a fixed size of 32x32pt. We recommend that you set the boundingBox to the same value
CGRect boundingBox = { .origin.x = 200.f, .origin.y = 400.f, .size.height = 32.f, .size.width = 32.f };
noteAnnotation.boundingBox = boundingBox;

// Add the newly created annotation to the document
[document addAnnotations:@[noteAnnotation] options:nil];

Sound Annotations

PSPDFSoundAnnotation API

To create a sound annotation with an existing audio file you need to use a Core Audio Format (.caf) file. You can convert an mp3 file to caf using afconvert in the Terminal.

1
/usr/bin/afconvert -f caff -d LEI16 sound.mp3 sound.caf

Learn more in Apple's Technical Q&A: QA1534 Creating Core Audio Format (.caf) Files.

For more information about converting the file in your own app, please refer to Apple's Audio Toolbox Convert File sample project.

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Create PSPDFDocument
let document = PSPDFDocument(url: documentURL)

// Create a new sound annotation with the sound URL.
// The sound file needs to be a `.caf` file.
guard let soundAnnotation = try? PSPDFSoundAnnotation(url: soundURL, error: nil) else {
    return nil
}

// Sound annotations are rendered as fixed size; much like how Adobe Acrobat renders them
// PSPDFKit will always render sound annotations at a fixed size of 74x44pt. We recommend that you set the boundingBox to the same value
let boundingBox = CGRect(x: 200, y: 400, width: 74, height: 44)
soundAnnotation.boundingBox = boundingBox

// Add the newly created annotation to the document
document.add([soundAnnotation])

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Create PSPDFDocument
PSPDFDocument *document = [[PSPDFDocument alloc] initWithURL:documentURL];

// Create a new sound annotation with the sound URL.
// The sound file needs to be a `.caf` file.
PSPDFSoundAnnotation *soundAnnotation = [[PSPDFSoundAnnotation alloc] initWithURL:soundURL error:&error];
if (!soundAnnotation) {
    // Handle Error
    return;
}

// Sound annotations are rendered as fixed size; much like how Adobe Acrobat renders them
// PSPDFKit will always render sound annotations at a fixed size of 74x44pt. We recommend that you set the boundingBox to the same value
CGRect boundingBox = { .origin.x = 200.f, .origin.y = 400.f, .size.height = 32.f, .size.width = 32.f };
noteAnnotation.boundingBox = boundingBox;

// Add the newly created annotation to the document
[document addAnnotations:@[soundAnnotation] options:nil];

Stamp Annotations

PSPDFStampAnnotation API

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Create PSPDFDocument
let document = PSPDFDocument(url: documentURL)

// Create a new stamp annotation using the appearance stream generator
let imageStamp = PSPDFStampAnnotation()

// Set the image 
imageStamp.image = UIImage(named: "exampleimage.jpg")

// Set the bounding box
let boundingBox = CGRect(x: 300, y: 150, width: 200, height: 200)
imageStamp.boundingBox = boundingBox

// Add the newly created annotation to the document
document.add([imageStamp])
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Create PSPDFDocument
PSPDFDocument *document = [[PSPDFDocument alloc] initWithURL:documentURL];

// Create a new stamp annotation using the appearance stream generator
PSPDFStampAnnotation *imageStamp = [[PSPDFStampAnnotation alloc] init];

// Set the image
imageStamp.image = [UIImage imageNamed:@"exampleimage.jpg"];
imageStamp.boundingBox = CGRectMake(300.f, 150.f, 200.f, 200.f);

// Set the bounding box
CGRect boundingBox = { .origin.x = 300.f, .origin.y = 150.f, .size.height = 200.f, .size.width = 200.f };
imageStamp.boundingBox = boundingBox;

// Add the newly created annotation to the document
[document addAnnotations:@[imageStamp] options:nil];