Flatten PDF Form Fields in iOS

Form elements in a PDF document can be flattened in the PSPDFKit UI by sharing (exporting) the document and choosing the Flatten Annotations option. They can also be flattened programmatically using the Processor class.

Form elements are of the special annotation type Annotation.Kind.widget, so please refer to our guide on flattening annotations, which also covers flattening for print and how to restrict permissions with a document after flattening. You can use the method discussed there to flatten all types of form elements:

guard let processorConfiguration = Processor.Configuration(document: originalDocument) else { return }

// Flatten all form elements.
processorConfiguration.modifyAnnotations(ofTypes: .widget, change: .flatten)

do {
    let processor = Processor(configuration: processorConfiguration, securityOptions: nil)
    try processor.write(toFileURL: outputFileURL)
} catch {
    // Handle error.
}

let flattenedDocument = Document(url: outputFileURL)
PSPDFProcessorConfiguration *processorConfiguration = [[PSPDFProcessorConfiguration alloc] initWithDocument:originalDocument];

// Flatten all form elements.
[processorConfiguration modifyAnnotationsOfTypes:PSPDFAnnotationTypeWidget change:PSPDFAnnotationChangeFlatten];

PSPDFProcessor *processor = [[PSPDFProcessor alloc] initWithConfiguration:processorConfiguration securityOptions:nil];
NSError *error;
if (![processor writeToFileURL:outputFileURL error:&error]) {
    // Handle error.
}

PSPDFDocument *flattenedDocument = [[PSPDFDocument alloc] initWithURL:outputFileURL];

Alternatively, you can flatten only certain types of form elements by specifying a PDFFormField.Kind and using Processor.Configuration.modifyForms(of:change:). For example, you might not want to flatten a signature annotation, as only the visual representation of the digital signature — and not the actual digital signature — would be included in the resulting document:

guard let processorConfiguration = Processor.Configuration(document: originalDocument) else { return }

// Flatten all form elements except signature elements.
processorConfiguration.modifyForms(of: .pushButton, change: .flatten)
processorConfiguration.modifyForms(of: .radioButton, change: .flatten)
processorConfiguration.modifyForms(of: .checkBox, change: .flatten)
processorConfiguration.modifyForms(of: .text, change: .flatten)
processorConfiguration.modifyForms(of: .listBox, change: .flatten)
processorConfiguration.modifyForms(of: .comboBox, change: .flatten)

do {
    let processor = Processor(configuration: processorConfiguration, securityOptions: nil)
    try processor.write(toFileURL: outputFileURL)
} catch {
    // Handle error.
}

let flattenedDocument = Document(url: outputFileURL)
PSPDFProcessorConfiguration *processorConfiguration = [[PSPDFProcessorConfiguration alloc] initWithDocument:originalDocument];

// Flatten all form elements except signature elements.
[processorConfiguration modifyFormsOfType:PSPDFFormFieldTypePushButton change:PSPDFAnnotationChangeFlatten];
[processorConfiguration modifyFormsOfType:PSPDFFormFieldTypeRadioButton change:PSPDFAnnotationChangeFlatten];
[processorConfiguration modifyFormsOfType:PSPDFFormFieldTypeCheckBox change:PSPDFAnnotationChangeFlatten];
[processorConfiguration modifyFormsOfType:PSPDFFormFieldTypeText change:PSPDFAnnotationChangeFlatten];
[processorConfiguration modifyFormsOfType:PSPDFFormFieldTypeListBox change:PSPDFAnnotationChangeFlatten];
[processorConfiguration modifyFormsOfType:PSPDFFormFieldTypeComboBox change:PSPDFAnnotationChangeFlatten];

PSPDFProcessor *processor = [[PSPDFProcessor alloc] initWithConfiguration:processorConfiguration securityOptions:nil];
NSError *error;
if (![processor writeToFileURL:outputFileURL error:&error]) {
    // Handle error.
}

PSPDFDocument *flattenedDocument = [[PSPDFDocument alloc] initWithURL:outputFileURL];