Adding Annotations in Objective-C with ComPDFKit

Tutorials | Objective-C · How to · Annotations Thu. 04 Aug. 2022

In addition to its primary textual content, a PDF file can contain annotations that represent links, form elements, highlighting circles, textual notes, and so on. Annotations allow users to mark up and comment on PDFs without altering the original author's content. Each annotation is associated with a specific location on a page.


ComPDFKit PDF SDK supports most annotation types and provides APIs of annotation creation, properties access and modification, appearance setting, and drawing. We will show you how to add annotations in Objective-C with our PDF SDK.





Annotation Appearances


Annotations may contain properties that describe their appearances — such as annotation color or shape. However, these don’t guarantee that the annotation will be displayed the same in different PDF viewers. To solve this problem, each annotation can define an appearance stream that should be used for rendering the annotation.


ComPDFKit PDF SDK will update the annotation appearance by default when you modify the annotation properties. You can also manually update the appearance by calling the updateAppearanceStream method, but you must call the updateAppearanceStream method manually when you modify the bounds of the FreeText, Stamp, and Signature annotation, refer to the following method in the CPDFAnnotation class.


- (void)updateAppearanceStream;


It’s easy to set up an annotation to show a custom appearance stream. This is typically done with stamp annotations because they have few other properties. A stamp annotation used this way is usually called an image annotation.


The following part introduces how to set annotation appearances that do not match page rotation. If set, do not rotate the annotation’s appearance to match the rotation of the page. The upper-left corner of the annotation bounds shall remain in a fixed location on the page.


CPDFKitShareConfig.enableAnnotationNoRotate = YES;


In addition, when it comes to the FreeText annotation, refer to the following method in the PDFListView class.


- (void)addAnnotationFreeTextAtPoint:(CGPoint)point forPage:(CPDFPage *)page;
- (void)drawPage:(CPDFPage *)page toContext:(CGContextRef)context;
- (void)moveAnnotation:(CPDFAnnotation *)annotation fromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint forType:(PDFAnnotationDraggingType)draggingType;


Predefine Annotations


ComPDFKit PDF SDK has default values for some annotation properties, such as colors and line widths for ink annotations. This is all handled in CPDFKitConfig which is a global singleton. You can access it with CPDFKitShareConfig. The current set of defaults is configured on the first run and saved in NSUserDefaults. 


// Author
CPDFKitShareConfig.annotationAuthor = @"";

// Color
CPDFKitShareConfig.highlightAnnotationColor = [UIColor yellowColor];
CPDFKitShareConfig.underlineAnnotationColor = [UIColor blueColor];
CPDFKitShareConfig.strikeoutAnnotationColor = [UIColor redColor];
CPDFKitShareConfig.squigglyAnnotationColor = [UIColor blackColor];
CPDFKitShareConfig.shapeAnnotationColor = [UIColor redColor];
CPDFKitShareConfig.shapeAnnotationInteriorColor = nil;
CPDFKitShareConfig.freehandAnnotationColor = [UIColor redColor];

// Opacity
CPDFKitShareConfig.markupAnnotationOpacity = 0.5;
CPDFKitShareConfig.shapeAnnotationOpacity = 1.0;
CPDFKitShareConfig.shapeAnnotationInteriorOpacity = 0.0;
CPDFKitShareConfig.freehandAnnotationOpacity = 1.0;

// Border Width
CPDFKitShareConfig.shapeAnnotationBorderWidth = 1.0;
CPDFKitShareConfig.freehandAnnotationBorderWidth = 1.0;



Adding Annotations


Access Annotations


CPDFAnnotation is the base class for all annotations. A CPDFAnnotation object by itself is not useful, only subclasses (like CPDFCircleAnnotation and CPDFTextAnnotation) are interesting. In parsing a PDF, however, any unknown or unsupported annotations will be represented as this base class.


- (NSArray<CPDFAnnotation *>)annotationsWithDocument:(CPDFDocument *)document {
  	NSMutableArray *annotations = [NSMutableArray array];
  	for (int i=0; i<document.pageCount; i++) {
      	CPDFPage *page = [document pageAtIndex:i];
      	[annotations addObjectsFromArray:[page annotations]];


The elements of the array will most likely be typed into subclasses of the CPDFAnnotation class.


How to add different annotations



NSURL *url = [NSURL fileURLWithPath:pdfPath];
CPDFDocument *document = [[[CPDFDocument alloc] initWithURL:url] autorelease];
CPDFPage *page = [document pageAtIndex:0];

CPDFTextAnnotation *text = [[[CPDFTextAnnotation alloc] initWithDocument:document] autorelease];
text.contents = @"test";
text.bounds = CGRectMake(0, 0, 50, 50);
text.color = [UIColor yellowColor];
[page addAnnotation:text];



NSURL *url = [NSURL fileURLWithPath:pdfPath];
CPDFDocument *document = [[[CPDFDocument alloc] initWithURL:url] autorelease];
CPDFPage *page = [document pageAtIndex:0];

CPDFDestination *dest = [[[CPDFDestination alloc] initWithDocument:document pageIndex:1] autorelease];
CPDFLinkAnnotation *link = [[[CPDFLinkAnnotation alloc] initWithDocument:document] autorelease];
link.bounds = CGRectMake(0, 0, 50, 50);
link.destination = dest;
//link.URL = @"https://www.";
[page addAnnotation:link];


Free Text

  NSURL *url = [NSURL fileURLWithPath:pdfPath];
  CPDFDocument *document = [[[CPDFDocument alloc] initWithURL:url] autorelease];
  CPDFPage *page = [document pageAtIndex:0];

  CPDFFreeTextAnnotation *freeText = [[[CPDFFreeTextAnnotation alloc] initWithDocument:document] autorelease];
  freeText.contents = @"test";
  freeText.bounds = CGRectMake(0, 0, 50, 50);
  freeText.font = [UIFont systemFontOfSize:12];
  freeText.fontColor = [UIColor redColor];
  freeText.alignment = NSTextAlignmentLeft;
  [page addAnnotation:freeText];



NSURL *url = [NSURL fileURLWithPath:pdfPath];
CPDFDocument *document = [[[CPDFDocument alloc] initWithURL:url] autorelease];
CPDFPage *page = [document pageAtIndex:0];

CPDFBorder *border = [[[CPDFBorder alloc] initWithStyle:CPDFBorderStyleDashed
                                              dashPattern:@[@(2), @(1)]] autorelease];

 // Square
CPDFSquareAnnotation *square = [[[CPDFSquareAnnotation alloc] initWithDocument:document] autorelease];
square.bounds = CGRectMake(0, 0, 50, 50);
square.color = [UIColor redColor];
square.interiorColor = [UIColor yellowColor];
square.opacity = 0.5;
square.interiorOpacity = 0.5;
square.border = border;
[page addAnnotation:square];

// Circle
CPDFCircleAnnotation *circle = [[[CPDFCircleAnnotation alloc] initWithDocument:document] autorelease];
circle.bounds = CGRectMake(0, 0, 50, 50);
circle.color = [UIColor redColor];
circle.interiorColor = [UIColor yellowColor];
circle.opacity = 0.5;
circle.interiorOpacity = 0.5;
circle.border = border;
[page addAnnotation:circle];
// Line
CPDFLineAnnotation *line = [[[CPDFLineAnnotation alloc] initWithDocument:document] autorelease];
line.startPoint = CGPointMake(0, 0);
line.endPoint = CGPointMake(50, 50);
line.startLineStyle = CPDFLineStyleNone;
line.endLineStyle = CPDFLineStyleClosedArrow;
line.color = [UIColor redColor];
line.interiorColor = [UIColor yellowColor];
line.opacity = 0.5;
line.interiorOpacity = 0.5;
line.border = border;
[page addAnnotation:line];


Note: CPDFLineAnnotation properties (startpoint, endpoint) point is specified in page-space coordinates. Page space is a coordinate system with the origin at the lower-left corner of the current page.



To add a highlight annotation to a PDF document page using the following method, and similarly add other markup annotations.


NSURL *url = [NSURL fileURLWithPath:pdfPath];
CPDFDocument *document = [[[CPDFDocument alloc] initWithURL:url] autorelease];
CPDFPage *page = [document pageAtIndex:0];

CPDFSelection *selection = ...;
NSMutableArray *quadrilateralPoints = [NSMutableArray array];
for (CPDFSelection *selection in selection.selectionsByLine) {
    CGRect bounds = selection.bounds;
    [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMinX(bounds), CGRectGetMaxY(bounds))]];
    [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMaxY(bounds))]];
    [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMinX(bounds), CGRectGetMinY(bounds))]];
    [quadrilateralPoints addObject:[NSValue valueWithCGPoint:CGPointMake(CGRectGetMaxX(bounds), CGRectGetMinY(bounds))]];

CPDFMarkupAnnotation *highlight = [[[CPDFMarkupAnnotation alloc] initWithDocument:document markupType:CPDFMarkupTypeHighlight] autorelease];
highlight.color = [UIColor yellowColor];
highlight.quadrilateralPoints = quadrilateralPoints;
[page addAnnotation:highlight];



NSURL *url = [NSURL fileURLWithPath:pdfPath];
CPDFDocument *document = [[[CPDFDocument alloc] initWithURL:url] autorelease];
CPDFPage *page = [document pageAtIndex:0];

// Standard
CPDFStampAnnotation *standard = [[[CPDFStampAnnotation alloc] initWithDocument:document type:0] autorelease];
[page addAnnotation:standard];

// Text
CPDFStampAnnotation *text = [[[CPDFStampAnnotation alloc] initWithDocument:document text:@"test" detailText:@"detail text" style:CPDFStampStyleRed shape:CPDFStampShapeArrowLeft] autorelease];
[page addAnnotation:text];

// Image
CPDFStampAnnotation *image = [[[CPDFStampAnnotation alloc] initWithDocument:document image:[UIImage imageNamed:@""]] autorelease];
[page addAnnotation:image];



Other operations


Delete Annotations

NSURL *url = [NSURL fileURLWithPath:pdfPath];
CPDFDocument *document = [[[CPDFDocument alloc] initWithURL:url] autorelease];
CPDFPage *page = [document pageAtIndex:0];

CPDFAnnotation *annotation = [[page annotations] objectAtIndex:0];
[page removeAnnotation:annotation];


Import & Export Annotations


When you export annotations, the snapshot of your PDF document’s annotations and forms will be saved in an XFDF file. It’s compatible with Adobe Acrobat and several other third-party frameworks. ComPDFKit PDF SDK for iOS supports both reading and writing XFDF. Please take a look at how to import & export annotations in code.


Importing XFDF

  NSURL *url = [NSURL fileURLWithPath:pdfPath];
  CPDFDocument *document = [[[CPDFDocument alloc] initWithURL:url] autorelease];

  NSString *path = [NSString stringWithString:xfdfPath];
  [document importAnnotationFromXFDFPath:path];


Exporting to XFDF

  NSURL *url = [NSURL fileURLWithPath:pdfPath];
  CPDFDocument *document = [[[CPDFDocument alloc] initWithURL:url] autorelease];

  NSString *path = [NSString stringWithString:xfdfPath];
  [document exportAnnotationToXFDFPath:path];


Flatten Annotations


Annotation flattening refers to the operation that changes annotations into a static area that is part of the PDF document, just like the other text and images in the document. A flattened annotation is visible but is non-editable by your users or by your app. ComPDFKit PDF SDK supports flattening annotations.


NSURL *url = [NSURL fileURLWithPath:pdfPath];
CPDFDocument *document = [[[CPDFDocument alloc] initWithURL:url] autorelease];

NSURL *surl = [NSURL fileURLWithPath:savePath];
[document writeFlattenToURL:surl];





Now you have a clear understanding of annotations. Just follow the methods above and take the annotation functions to your software. The SDK package you will need can be downloaded for free and if you are interested in our SDK, please contact us for a free trial. We will keep sharing the knowledge about PDF SDK.

Ready to Get Started?

Download our all-in-one ComPDFKit for free and run it to your project within minutes!