Skip to content

PDF-SDK 2.4.1 is out.See what’s new

PDF-SDK
Skip to Content
Docs

iOS, iPadOS & Mac Catalyst API reference

Generated from the Swift package's sources. For a guided introduction — installing the package, the license key, presenting the editor, customizing it — start with the iOS, iPadOS & Mac Catalyst guide.

Module PDFEditorUI (iOS, iPadOS, Mac Catalyst): 54 public types and 383 members, generated from the SDK's sources at build time, so this page cannot drift from them.

The editor

PDFEditorMode

public enum PDFEditorMode: CaseIterable

The mode the editor opens in, chosen by the HOST app when it presents PDFEditorView / PDFEditorViewController. Defaults to .contentEditor. (Public façade over the internal EditorMode.)

contentEditor

case contentEditor

viewer

case viewer

annotate

case annotate

fillSign

case fillSign

insert

case insert

draw

case draw

form

case form

PDFEditorTool

public enum PDFEditorTool: CaseIterable

A specific tool the HOST can pre-arm when it presents PDFEditorView / PDFEditorViewController, INDEPENDENT of initialMode. Every combination is valid and OPTIONAL: • tool alone → the editor opens in the mode that owns the tool (owningMode) and arms it; • tool + initialMode → the tool is armed within the mode the host chose; • initialMode alone → that mode, nothing pre-armed (today's behaviour); • neither → the editor opens exactly as it does now (.contentEditor, nothing armed).

Arming behaves EXACTLY as if the user tapped that tool in the mode toolbar — so .image opens the Photos / Files source picker, .signature opens the signature pad, .addText arms tap-to-place, .highlight arms the highlighter, .shapeRectangle arms rubber-band placement, etc. (Public façade over EditorToolAction.)

addText

case addText

image

case image
case link

insertPage

case insertPage

multiSelect

case multiSelect

highlight

case highlight

underline

case underline

strikeout

case strikeout

squiggly

case squiggly

signature

case signature

stamp

case stamp

note

case note

draw

case draw

shapeRectangle

case shapeRectangle

shapeEllipse

case shapeEllipse

shapeLine

case shapeLine

shapeArrow

case shapeArrow

formTextField

case formTextField

formCheckBox

case formCheckBox

formRadioButton

case formRadioButton

formListBox

case formListBox

formDropdown

case formDropdown

PDFEditorView

public struct PDFEditorView: View

The PDF editor as a SwiftUI view. Open a PDF by file URL, edit it, and receive the edited PDF bytes via onSave. Present it however you like (a .fullScreenCover is typical).

.fullScreenCover(isPresented: $editing) {
    PDFEditorView(url: pdfURL) { edited in
        try? edited.write(to: pdfURL, options: .atomic)   // save wherever you want
        editing = false
    } onCancel: { editing = false }
}

Write it atomically, and drop any PDFDocument/PDFView you have open on that same path first. .atomic writes a temp file and renames, so an already-open document keeps its intact inode.

init

public init(
    url: URL,
    initialMode: PDFEditorMode? = nil,
    initialTool: PDFEditorTool? = nil,
    configuration: PDFEditorConfiguration = PDFEditorConfiguration(),
    onSave: @escaping (Data) -> Void,
    onCancel: @escaping () -> Void,
    onSharePDF: ((Data) -> Void)? = nil,
    onPrint: ((Data) -> Void)? = nil,
    onFlattenAndShare: ((Data) -> Void)? = nil,
    onDigitallySigned: ((Data) -> Void)? = nil,
    onUnsavedChangesChanged: ((Bool) -> Void)? = nil,
    onDocumentReady: ((PDFDocumentEditor) -> Void)? = nil,
)
  • Parameters:
  • url: the PDF file to edit. The editor opens on the first page.
  • initialMode: the mode the editor opens in. Optional — omit (or nil) for the default. When a initialTool is given without a mode, the editor opens in the mode that owns the tool; when neither is given it opens in .contentEditor, exactly as before.
  • initialTool: a tool to pre-arm on open (Add Text, Image, Link, Highlight, Signature, a shape, …), INDEPENDENT of initialMode. Optional — omit (or nil) to open with nothing armed. Arming behaves exactly like tapping the tool (e.g. .image opens the source picker, .signature the signature pad).
  • configuration: which modes, tools and ⋮-menu items the editor offers, its colour scheme, the tools' first-use styles, zoom range and haptics. Optional — the default is the editor as it ships. See PDFEditorConfiguration.
  • onSave: called with the edited PDF's bytes when the user saves.
  • onCancel: called when the user closes the editor without saving.
  • onSharePDF: if provided, the ⋮ menu's Share PDF hands back the edited PDF bytes instead of presenting the system share sheet — intercept it for a paywall, custom share UI, upload, etc.
  • onPrint: if provided, the ⋮ menu's Print hands back the edited PDF bytes instead of opening the system print panel.
  • onFlattenAndShare: if provided, the ⋮ menu's Flatten & Share hands back the FLATTENED PDF bytes (form fields baked into page content) instead of presenting the system share sheet. Only shown for documents that contain a form. When nil, the editor falls back to presenting the signed PDF in the system share sheet (and logs a note), so signatures are never silently lost.
  • onUnsavedChangesChanged: called with true as soon as the document has edits that aren't saved, and false once they are. On Mac Catalyst you should track this: the window's red close button is an AppKit affordance that UIKit scene APIs cannot veto, so the editor cannot put up its own "unsaved changes" prompt there — closing the window would discard the edits silently. Use this to block or confirm termination in your app (or to auto-save).
  • onDocumentReady: called once, when the document is open, with a PDFDocumentEditor for it — read every layer, change text, styles and geometry, add and remove layers, fill forms, all from code. Its changes show in the editor at once and the user can undo them. Use it on the main thread.

body

public var body: some View

PDFEditorViewController

public final class PDFEditorViewController: UIHostingController<PDFEditorView>

The PDF editor as a UIKit view controller (a UIHostingController around PDFEditorView). Present it from any view controller; it defaults to full-screen presentation.

let editor = PDFEditorViewController(url: pdfURL,
    onSave: { data in /* save */ }, onCancel: { [weak self] in self?.dismiss(animated: true) })
present(editor, animated: true)

init

public init(
    url: URL,
    initialMode: PDFEditorMode? = nil,
    initialTool: PDFEditorTool? = nil,
    configuration: PDFEditorConfiguration = PDFEditorConfiguration(),
    onSave: @escaping (Data) -> Void,
    onCancel: @escaping () -> Void,
    onSharePDF: ((Data) -> Void)? = nil,
    onPrint: ((Data) -> Void)? = nil,
    onFlattenAndShare: ((Data) -> Void)? = nil,
    onDigitallySigned: ((Data) -> Void)? = nil,
    onUnsavedChangesChanged: ((Bool) -> Void)? = nil,
    onDocumentReady: ((PDFDocumentEditor) -> Void)? = nil,
)
  • Parameters:
  • url: the PDF file to edit. The editor opens on the first page.
  • configuration: modes, tools, ⋮-menu items, colour scheme, tool styles, zoom, haptics — see PDFEditorConfiguration. Optional.
  • onSave: called with the edited PDF's bytes when the user saves.
  • onCancel: called when the user closes the editor without saving.
  • onSharePDF / onPrint / onFlattenAndShare: optional interceptors for the matching ⋮-menu export actions — each hands back the PDF bytes instead of presenting the system sheet (see PDFEditorView).
  • onDigitallySigned: if provided, called with the signed PDF's bytes after the user digitally signs; when unset the signed document is handed to the system share sheet instead (see PDFEditorView).
  • onDocumentReady: the open document as a PDFDocumentEditor, for changes from code (see PDFEditorView).

present

public override func present(
    _ viewControllerToPresent: UIViewController,
    animated flag: Bool,
    completion: (() -> Void)? = nil,
)

A presented controller takes its style from the WINDOW, not from the controller that presented it, so the override above reached the editor but not its sheets: a host that pinned .dark got a dark editor with a light Tools sheet, font picker and signature pad. SwiftUI presents those through this controller, so the pinned style is handed on here.

Customization

SignaturePlacement

public enum SignaturePlacement: String, CaseIterable, Identifiable, Sendable

Where the visible signature box is drawn on the current page.

bottomRight

case bottomRight = "Bottom Right", bottomLeft = "Bottom Left"

topRight

case topRight = "Top Right", topLeft = "Top Left"

invisible

case invisible = "Invisible"

title

public var title: String

The placement's name in the editor's language (the raw value is the stable English id).

id

public var id: String

init

public init?(name: String)

The cross-platform name (bottomRight, bottomLeft, topRight, topLeft, invisible), as the Flutter / React Native options and Android's PdfSignaturePlacement spell it. Case-insensitive.

PDFEditorLocalization

public struct PDFEditorLocalization

How the editor is translated. PDFEditorConfiguration.localization.

language

public var language: String?

The editor's language as a BCP-47 code ("hi", "ar", "pt-BR"). Picks the .lproj table, the date format of stamps, and — for right-to-left languages — the layout direction. nil = the app's current language.

strings

public var strings: [String: String] = [:]

Key → text. Placeholders {1}, {2} … are filled in by the editor.

provider

public var provider: ((_ key: String, _ english: String) -> String?)?

Asked for every key strings doesn't have; return nil to fall through.

bundle

public var bundle: Bundle?

Where to look for <language>.lproj/<tableName>.strings. nil = the app's main bundle.

tableName

public var tableName = "PDFEditor"

layoutDirection

public var layoutDirection: LayoutDirection = .automatic

Left-to-right or right-to-left chrome.

init

public init(
    language: String? = nil,
    strings: [String: String] = [:],
    provider: ((_ key: String, _ english: String) -> String?)? = nil,
)

PDFColor

public struct PDFColor: Hashable, Sendable

A colour as the engine stores it: 8-bit RGBA.

red

public var red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8

init

public init(red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8 = 255)

init

public init(rgba: UInt32)

0xRRGGBBAA.

init

public init(_ color: UIColor)

rgba

public var rgba: UInt32

uiColor

public var uiColor: UIColor

black

public static let black = PDFColor(rgba: 0x000000FF)

white

public static let white = PDFColor(rgba: 0xFFFFFFFF)

clear

public static let clear = PDFColor(rgba: 0)

PDFEditorConfiguration

public struct PDFEditorConfiguration

One editor's customisation. Every property has the SDK's own behaviour as its default, so PDFEditorConfiguration() is exactly the editor you get without passing one.

modes

public var modes: [PDFEditorMode] = []

The modes the Tools sheet offers, in the order given. Duplicates are dropped. An empty list means every mode. A mode whose tools are ALL hidden (see hiddenTools) is dropped too, except .viewer, which has no tools. With one mode left, the header shows its name without the mode picker.

initialMode must be one of these; otherwise the editor opens in the first one. Form Editor stays unavailable on Mac Catalyst whatever this says.

hiddenTools

public var hiddenTools: Set<PDFEditorTool> = []

Tools removed from every mode's toolbar. .addText appears in several modes and is hidden in all of them. An initialTool that is hidden is not armed.

hiddenMenuItems

public var hiddenMenuItems: Set<PDFEditorMenuItem> = []

Items removed from the ⋮ menu. Items the document can't use (Flatten & Share without a form) are hidden regardless.

colorScheme

public var colorScheme: PDFEditorColorScheme = .system

Light, dark, or follow the system (default). Applies to the editor's own presentation.

toolDefaults

public var toolDefaults = PDFEditorToolDefaults()

The style each tool starts with the first time it is used. Once the user picks a colour or opacity, the editor remembers their choice on this device and that wins, exactly as it does today.

zoomRange

public var zoomRange: ClosedRange<CGFloat> = PDFEditorConfiguration.supportedZoomRange

The page zoom range, where 1 is the page fitted to the screen. Clamped to what the editor renders crisply (50 %…300 %) and always widened to include 1, so this can narrow the range (1...1 turns pinch-zoom off) but not widen it.

haptics

public var haptics: Bool = true

Haptic feedback on taps, snaps and alignment guides. Default on.

showsUsageHints

public var showsUsageHints: Bool = true

Default on.

interfaceFontFamily

public var interfaceFontFamily: String?

The font family for the editor's own text — toolbar labels, the header, sheets, panels — e.g. "Avenir Next" or a family your app bundles (list its files under UIAppFonts). Sizes stay the editor's, and weights come from the family's own faces. nil (the default) is the system font. A family the app can't load is ignored (and logged). SF Symbols, system menus, alerts and the keyboard keep the system font; the document's own text is never set in it.

fonts

public var fonts: [PDFEditorFont] = []

Fonts of your own for the DOCUMENT's text, listed first in the text font picker under fontsTitle. Each must be a TrueType/OpenType file with ordinary outlines (the same test an imported font passes); one that isn't is skipped and logged. Applying one embeds it in the PDF, like any other font the user picks.

fontsTitle

public var fontsTitle = "Featured"

The picker section fonts appear under.

showsStandardFonts

public var showsStandardFonts = true

The picker's other sections: the standard PDF fonts (Helvetica, Times and Courier, which every PDF reader has, so choosing one embeds nothing), the PDF's own embedded fonts, the device's fonts, and the fonts the user imported (with the "+" that imports one). Hide them to limit text to your fonts.

showsDocumentFonts

public var showsDocumentFonts = true

showsDeviceFonts

public var showsDeviceFonts = true

allowsFontImport

public var allowsFontImport = true

newTextFont

public var newTextFont: PDFEditorFont?

A font of yours for NEW text: a box the user places is set in it. Its size and colour still follow the text around it, as they always do. Validated like fonts (one that isn't usable is ignored and logged) and embedded when the first box is placed. nil (the default) matches the page's own text.

selectionColor

public var selectionColor: UIColor?

The colour of the selection: the box around a selected layer, its handles' rings, the rotation knob, the text caret, the text-selection band and its grab handles, and the guide that marks alignment with the page. Always drawn opaque. A dynamic colour follows the editor's light/dark scheme. nil = the accent (colors.accent), else system blue.

handleFillColor

public var handleFillColor: UIColor?

The handles' (and the rotation knob's) fill. nil = white.

handleShape

public var handleShape: PDFEditorHandleShape = .roundedSquare

handleScale

public var handleScale: CGFloat = 1

Handle and knob size, 0.75…1.5 (clamped). A mouse's or trackpad's reach for them follows the size; a finger's is already wider than the largest handle, and how small a layer can be resized doesn't change.

selectionBorderWidth

public var selectionBorderWidth: CGFloat = 1.5

The selection box's and the handles' outline, in points: 1…3 (clamped).

rotateIcon

public var rotateIcon: UIImage?

The glyph inside the rotation knob, drawn as a template: its shape, filled with selectionColor. A single-colour image with a transparent background; it's fitted into the knob. nil = the built-in arrow.

searchHighlightColor

public var searchHighlightColor: UIColor?

The wash over every search match, and over the current one (with a ring). Only the colour is used: the translucency is the editor's, so the text under a highlight always reads. nil = yellow / orange.

searchCurrentHighlightColor

public var searchCurrentHighlightColor: UIColor?

colors

public var colors = PDFEditorColors()

THE EDITOR'S OWN COLOURS — its accent, the canvas around the pages, the toolbars and panels, and what is drawn on them. Each one left nil keeps the editor's own, so a host can change just the accent without taking on the rest.

Set a toolbarBackground and leave toolbarForeground nil, and the editor picks white or near-black ink for it by its luminance, so a brand colour is never paired with unreadable labels. The ⋮ menu and the system sheets (share, print, photo picker) are drawn by iOS and keep the system's colours; they take the accent.

markupColors

public var markupColors: [UIColor] = []

The Annotate colour row (highlight, underline, strikethrough, squiggly), left to right. Empty = the editor's own.

inkColors

public var inkColors: [UIColor] = []

The Draw ink bar's colours on Mac Catalyst. Empty = the editor's own.

signatureColors

public var signatureColors: [UIColor] = []

The signature pad's ink colours; the first is the default ink. Empty = the editor's own.

stamps

public var stamps: [PDFEditorStamp] = []

The Stamp tool's presets, in order. Empty = the editor's own (APPROVED, DRAFT, CONFIDENTIAL, REJECTED, FINAL and today's date). .date(color:) is a stamp that reads the day it's placed.

allowsCustomStamp

public var allowsCustomStamp = true

The stamp picker's Custom Photo… button.

fontSizes

public var fontSizes: [Int] = []

The font-size list, in points (1…400, duplicates dropped, sorted). Empty = the editor's own 8…144.

signatureMethods

public var signatureMethods: [PDFEditorSignatureMethod] = []

The signature pad's tabs, in order. Empty = all of them. .eSign shows only when digital signing is wired, and a list that leaves nothing falls back to .draw.

signaturePlacement

public var signaturePlacement: SignaturePlacement = .bottomRight

Where the e-Sign tab's Placement picker starts (the user can still change it). Default .bottomRight.

showsUndoRedo

public var showsUndoRedo = true

The floating pills along the bottom: undo / redo, the page navigator, and zoom.

showsPageNavigator

public var showsPageNavigator = true

showsZoomControls

public var showsZoomControls = true

localization

public var localization = PDFEditorLocalization()

THE EDITOR'S LANGUAGE — every word it shows, by key: a dictionary, a lookup function, or the host's own <language>.lproj/PDFEditor.strings. Untranslated keys stay English; right-to-left languages flip the chrome. The key list is docs/localization/strings.json. The names below (toolTitles…) win over it.

toolTitles

public var toolTitles: [PDFEditorTool: String] = [:]

Your own names for tools, e.g. [.highlight: "Mark"]. A tool that appears in several modes (.addText) takes the name everywhere. Empty strings are ignored.

toolIcons

public var toolIcons: [PDFEditorTool: UIImage] = [:]

Your own icons for tools. Drawn as a template (tinted like the built-in glyphs, blue when armed) at 20 pt, so use a single-colour image with a transparent background.

modeTitles

public var modeTitles: [PDFEditorMode: String] = [:]

Your own names for modes: the header and the Tools sheet.

modeIcons

public var modeIcons: [PDFEditorMode: UIImage] = [:]

Your own icons for modes in the Tools sheet, drawn as a template on the mode's coloured tile.

menuItemTitles

public var menuItemTitles: [PDFEditorMenuItem: String] = [:]

Your own names and icons for the ⋮ menu's items.

menuItemIcons

public var menuItemIcons: [PDFEditorMenuItem: UIImage] = [:]

headerIcons

public var headerIcons: [PDFEditorHeaderButton: UIImage] = [:]

Your own icons for the header's buttons, drawn as a template.

actionTitles

public var actionTitles: [PDFEditorAction: String] = [:]

Your own names for the SUB-TOOLS: the controls that appear once something is selected (the property bar's Edit, Color, Font, Crop, Cut, Delete…), the menu over the selection (Edit · Duplicate · Delete), and the page panel's page actions. A name applies wherever that action appears. Empty names are ignored.

actionIcons

public var actionIcons: [PDFEditorAction: UIImage] = [:]

Your own icons for sub-tools, drawn as templates like toolIcons. Colour wells, steppers and the size button show a value rather than an icon, so an icon there is ignored.

hiddenActions

public var hiddenActions: Set<PDFEditorAction> = []

Sub-tools removed wherever they appear. Nothing replaces an action you hide.

actionOrder

public var actionOrder: [PDFEditorAction] = []

Listed sub-tools first, in this order, in every bar and menu that has them; the rest keep the editor's order. The bar's dividers follow the new order.

customTools

public var customTools: [PDFEditorMode: [PDFEditorCustomAction]] = [:]

A tap commits any edit in progress and calls the handler; the editor does nothing else. A mode with only custom tools still shows its toolbar — even .viewer.

customMenuItems

public var customMenuItems: [PDFEditorCustomAction] = []

⋮ menu items of your own, after the built-in items (reorder with menuOrder).

toolOrder

public var toolOrder: [PDFEditorMode: [PDFEditorToolbarItem]] = [:]

The order of a mode's toolbar. Listed items come first, in this order; everything else the mode has follows in its usual order, so ordering never hides a tool (that's hiddenTools). A tool the mode doesn't carry is ignored: tools can be reordered within a mode, not moved to another.

config.toolOrder[.fillSign] = [.custom("approve"), .tool(.signature)]

menuOrder

public var menuOrder: [PDFEditorMenuEntry] = []

The order of the ⋮ menu, with the same rule: listed items first, the rest after in the usual order.

supportedZoomRange

public static let supportedZoomRange: ClosedRange<CGFloat> = 0.5...3

The widest zoom range the editor supports.

init

public init()

PDFEditorHandleShape

public enum PDFEditorHandleShape

The shape of the selection handles.

roundedSquare

case roundedSquare

circle

case circle

square

case square

PDFEditorFont

public struct PDFEditorFont

A font file of the host's, for PDFEditorConfiguration.fonts.

init

public init(url: URL)

A font file — typically one in your app bundle (Bundle.main.url(forResource: "Brand", withExtension: "ttf")).

init

public init(data: Data)

Font bytes you already hold (downloaded, decrypted, generated).

PDFEditorCustomAction

public struct PDFEditorCustomAction

A button of the host's own, in a mode's toolbar or the ⋮ menu.

id

public var id: String

Unique among your custom actions; toolOrder / menuOrder refer to it by this.

title

public var title: String

image

public var image: UIImage?

Drawn as a template at 20 pt. nil shows a generic glyph in the toolbar and none in the menu.

handler

public var handler: @MainActor (PDFEditorActionContext) -> Void

Called on the main thread, after any edit in progress was committed.

init

public init(
    id: String,
    title: String,
    image: UIImage? = nil,
    handler: @escaping @MainActor (PDFEditorActionContext) -> Void,
)

PDFEditorActionContext

public struct PDFEditorActionContext

What a custom action's handler can see of the document.

pageIndex

public let pageIndex: Int

The page on screen, 0-based, and the page count.

pageCount

public let pageCount: Int

currentPDF

public func currentPDF() -> Data?

The document as it stands, every edit included, as PDF bytes. Nothing is saved and onSave is not called; this is a copy. nil only if the export failed.

PDFEditorToolbarItem

public enum PDFEditorToolbarItem: Hashable

An entry in toolOrder: a built-in tool, or one of your customTools by id.

tool

case tool(PDFEditorTool)

custom

case custom(String)

PDFEditorMenuEntry

public enum PDFEditorMenuEntry: Hashable

An entry in menuOrder: a built-in ⋮ item, or one of your customMenuItems by id.

item

case item(PDFEditorMenuItem)

custom

case custom(String)

PDFEditorAction

public enum PDFEditorAction: String, CaseIterable, Hashable

A sub-tool: a control that appears once something is selected — in the property bar that replaces the mode toolbar, or in the menu over the selection — or on a page in the page panel. Customise them with PDFEditorConfiguration.actionTitles, actionIcons, hiddenActions and actionOrder.

multiSelect

case multiSelect

Multi: add to / remove from a multi-layer selection.

editText

case editText

Edit a text layer's words (bar and menu).

textColor

case textColor

A text layer's colour well.

font

case font

The font picker.

textStyle

case textStyle

Bold · Italic · Underline · Strikethrough (one group; its title is the caption under it).

fontSize

case fontSize

The font-size button.

opacity

case opacity

The opacity stepper.

strokeColor

case strokeColor

A shape's outline colour well.

fillColor

case fillColor

A shape's or path's fill colour well.

strokeWidth

case strokeWidth

A shape's outline width stepper.

editNote

case editNote

Edit a sticky note (bar and menu).

noteColor

case noteColor

A sticky note's card colour well.

resign

case resign

Draw a placed signature again (bar and menu).

replaceImage

case replaceImage

Replace an image (bar and menu).

crop

case crop

Crop an image or signature.

playSound

case playSound

Play / pause / replay a sound note.

case link

Link a layer to a URL or page.

cut

case cut

copy

case copy

duplicate

case duplicate

Duplicate a layer or form field (menu).

delete

case delete

Delete a layer or form field (bar and menu).

formFill

case formFill

A form field's menu: fill it in ("Edit Text", "Toggle" or "Choose…", by the field's kind).

formOptions

case formOptions

A list or dropdown field's Options.

formRadioGroup

case formRadioGroup

A radio button's Group.

formColors

case formColors

A form field's Color submenu (fill, border, text).

formBorderWidth

case formBorderWidth

A form field's Border Width submenu.

paste

case paste

Paste, on the empty page's menu.

rotatePageLeft

case rotatePageLeft

The page panel's actions on a page.

rotatePageRight

case rotatePageRight

duplicatePage

case duplicatePage

insertBlankPage

case insertBlankPage

deletePage

case deletePage

init

public init?(name: String)

The action for a cross-platform name — the same spelling as the case (editText, rotatePageLeft, …).

PDFEditorStamp

public struct PDFEditorStamp

A rubber stamp for PDFEditorConfiguration.stamps: its text and its ink.

text

public var text: String

color

public var color: UIColor

isDate

public var isDate: Bool

Reads the date it's placed instead of text.

init

public init(_ text: String, color: UIColor)

date

public static func date(color: UIColor) -> PDFEditorStamp

Today's date, formatted for the device's locale when the stamp is placed.

PDFEditorSignatureMethod

public enum PDFEditorSignatureMethod: String, CaseIterable

The signature pad's tabs, for PDFEditorConfiguration.signatureMethods.

draw

case draw, type, image, eSign

PDFEditorHeaderButton

public enum PDFEditorHeaderButton: CaseIterable

The header's buttons.

back

case back

pages

case pages

more

case more

done

case done

PDFEditorMenuItem

public enum PDFEditorMenuItem: CaseIterable

The ⋮ (More) menu's items.

search

case search

managePages

case managePages

sharePDF

case sharePDF

print

case print

flattenAndShare

case flattenAndShare

resetForm

case resetForm

resetToOriginal

case resetToOriginal

PDFEditorColorScheme

public enum PDFEditorColorScheme

The editor's colour scheme.

system

case system

light

case light

dark

case dark

PDFEditorColors

public struct PDFEditorColors

The editor's colours, for PDFEditorConfiguration.colors. nil keeps the editor's own.

accent

public var accent: UIColor?

Buttons, the armed tool, Done, switches, the current page — anything that says "this one".

onAccent

public var onAccent: UIColor?

Text and glyphs drawn ON the accent (Done's check, the open pages button). Default white.

canvasBackground

public var canvasBackground: UIColor?

Behind and around the pages.

toolbarBackground

public var toolbarBackground: UIColor?

The header, the mode toolbar, the property bars and the floating pills. Replaces their frosted material (and, on iOS 26, their Liquid Glass) with this solid colour.

toolbarForeground

public var toolbarForeground: UIColor?

Icons and labels on those bars, and the primary text in the editor's own panels.

secondaryForeground

public var secondaryForeground: UIColor?

Captions, hints, placeholders, inactive labels. Default: toolbarForeground at reduced strength.

panelBackground

public var panelBackground: UIColor?

The editor's own sheets (Tools, fonts, pages). Default: toolbarBackground, or the system's.

destructive

public var destructive: UIColor?

Delete and other destructive actions.

init

public init(
    accent: UIColor? = nil,
    onAccent: UIColor? = nil,
    canvasBackground: UIColor? = nil,
    toolbarBackground: UIColor? = nil,
    toolbarForeground: UIColor? = nil,
    secondaryForeground: UIColor? = nil,
    panelBackground: UIColor? = nil,
    destructive: UIColor? = nil,
)

PDFEditorMarkupStyle

public struct PDFEditorMarkupStyle

A text-markup tool's first-use style. opacity is clamped to 0.1…1 (the slider's range).

color

public var color: UIColor

opacity

public var opacity: CGFloat

init

public init(color: UIColor, opacity: CGFloat = 1)

PDFEditorInkStyle

public struct PDFEditorInkStyle

width is clamped to 1…30 points, opacity to 0.1…1. width is clamped to 1…30 and opacity to 0.1…1.

color

public var color: UIColor

width

public var width: CGFloat

opacity

public var opacity: CGFloat

init

public init(color: UIColor, width: CGFloat = 5, opacity: CGFloat = 1)

PDFEditorToolDefaults

public struct PDFEditorToolDefaults

The defaults are the editor's own.

highlight

public var highlight = PDFEditorMarkupStyle(
    color: warmYellow,
    opacity: 0.5,
)

A see-through wash, so the text reads through it.

underline

public var underline = PDFEditorMarkupStyle(color: warmYellow)

strikeout

public var strikeout = PDFEditorMarkupStyle(color: warmYellow)

squiggly

public var squiggly = PDFEditorMarkupStyle(color: warmYellow)

ink

public var ink = PDFEditorInkStyle(color: .black)

init

public init()

PDFEditorAppearance

public enum PDFEditorAppearance

Public appearance knobs the host app can tune from OUTSIDE the SDK (before or while an editor is shown).

dockScale

@MainActor public static var dockScale: CGFloat = 0

Size multiplier for the floating tool DOCK (its icons, labels, chips, paddings — the whole capsule grows/shrinks, and its snap positioning follows because the metrics feed the layout, not a render transform). 0 = AUTOMATIC: 1.0 on iPhone, 1.35 on iPad (the dock reads small on the larger iPad screen). Set any value > 0 to force a specific scale for testing/tuning; clamped to 0.5…3.0.

PDFEditorAppearance.dockScale = 1.6   // bigger dock on iPad for testing

PDFSigner.Appearance

public struct Appearance

reason

public var reason: String?

location

public var location: String?

page

public var page: Int?

Page index for a VISIBLE signature (draws the box); nil = invisible.

rect

public var rect: CGRect?

Rect in PDF points (x, y from the page's bottom-left, width, height).

init

public init(
    reason: String? = nil,
    location: String? = nil,
    page: Int? = nil,
    rect: CGRect? = nil,
)

PDFEditorLocalization.LayoutDirection

public enum LayoutDirection: Sendable

Signing

SignaturesView

public struct SignaturesView: View

onClose

public var onClose: (() -> Void)?

init

public init(pdf: Data, onClose: (() -> Void)? = nil)

body

public var body: some View

DigitalSignFormModel

public final class DigitalSignFormModel: ObservableObject

name

@Published public var name: String

org

@Published public var org = ""

email

@Published public var email = ""

reason

@Published public var reason = peL(
    "i_approve_this_document",
    "I approve this document",
)

location

@Published public var location = ""

placement

@Published public var placement: SignaturePlacement = .bottomRight

makeNew

@Published public var makeNew: Bool

existingSignerName

public let existingSignerName: String?

onCanSignChanged

public var onCanSignChanged: (() -> Void)?

Fired whenever canSign might have changed, so the host (pad) can enable/disable Done.

init

public init(
    existingSignerName: String?,
    placement: SignaturePlacement = .bottomRight,
)

canSign

public var canSign: Bool

DigitalID

public struct DigitalID

A signing identity: an RSA private key plus its self-signed X.509 certificate (DER).

privateKey

public let privateKey: SecKey

certificateDER

public let certificateDER: [UInt8]

createSelfSigned

public static func createSelfSigned(
    commonName: String,
    organization: String? = nil,
    email: String? = nil,
    validDays: Int = 3650,
    permanentTag: String? = nil,
) throws -> DigitalID

Create a fresh self-signed identity (ComPDFKit's "create a new Digital ID"). commonName is the signer shown in the signature; org/email are optional.

detachedCMS

public func detachedCMS(
    messageDigest: [UInt8],
    signingTime: Date,
) throws -> [UInt8]

Build the detached PKCS#7 CMS over a message digest (SHA-256, 32 bytes) that the engine supplies.

PDFSigner

public enum PDFSigner

sign

public static func sign(
    pdf: Data,
    with id: DigitalID,
    signerName: String,
    appearance: Appearance = Appearance(),
) throws -> Data

Sign pdf with id, returning the signed document. signerName is what the appearance shows.

DigitalIDStore

public final class DigitalIDStore: @unchecked Sendable

Stores ONE self-signed Digital ID across launches — the private key in the Keychain, the certificate and its DER sub-pieces in UserDefaults — so "Sign" reuses the same identity instead of minting a new cert each time (ComPDFKit's "manage Digital IDs", minimal single-ID form). Lives in this file for access to DigitalID's internal members.

shared

public static let shared = DigitalIDStore()

hasID

public var hasID: Bool

signerName

public var signerName: String?

current

public func current() -> DigitalID?

The stored identity, or nil if none has been created.

create

public func create(
    commonName: String,
    organization: String? = nil,
    email: String? = nil,
) throws -> DigitalID

loadOrCreate

public func loadOrCreate(
    commonName: String,
    organization: String? = nil,
    email: String? = nil,
) throws -> DigitalID

Reuse the stored ID, or create one from the given details if none exists.

reset

public func reset()

SignatureStatus

public struct SignatureStatus: Identifiable, Sendable

Result for one signature in a document.

id

public let id: Int

signerName

public let signerName: String

signingTime

public let signingTime: String

reason

public let reason: String

isValid

public let isValid: Bool

coversWholeDocument

public let coversWholeDocument: Bool

summary

public let summary: String

certificationLevel

public let certificationLevel: Int

certificationSummary

public var certificationSummary: String?

Human description of the certification, or nil for an ordinary approval signature.

PDFSignatureVerifier

public enum PDFSignatureVerifier

verify

public static func verify(pdf: Data) -> [SignatureStatus]

DigitalID.SignError

public enum SignError: Error

Document API

PDFDocumentBridgeError

public struct PDFDocumentBridgeError: Error, Equatable

Why a bridged document call failed.

code

public let code: String

message

public let message: String

PDFLayer

public struct PDFLayer: Identifiable, Hashable, Sendable

One layer of a page, read as data. Geometry is in page points with the origin at the page's top-left. id addresses the layer in every call that changes it, and keeps naming it while other layers change.

page

public let page: Int

id

public let id: Int

kind

public let kind: Kind

frame

public let frame: CGRect

rotation

public let rotation: Double

Degrees, clockwise as seen.

opacity

public let opacity: Double

zIndex

public let zIndex: Int

Stacking rank on the page: 0 is the bottom layer.

public let link: String?

text

public let text: String?

fontName

public let fontName: String?

fontSize

public let fontSize: Double?

isBold

public let isBold: Bool

isItalic

public let isItalic: Bool

isUnderlined

public let isUnderlined: Bool

isStruckThrough

public let isStruckThrough: Bool

isFontEmbedded

public let isFontEmbedded: Bool

isSymbolic

public let isSymbolic: Bool

Set entirely in symbol fonts — an ornament or a check box drawn as letters. Not language: leave it out of any text processing (rewriting, spell checking, search).

textColor

public let textColor: PDFColor?

highlightColor

public let highlightColor: PDFColor?

pixelSize

public let pixelSize: CGSize?

note

public let note: String?

noteColor

public let noteColor: PDFColor?

noteTextColor

public let noteTextColor: PDFColor?

shape

public let shape: Shape?

fillColor

public let fillColor: PDFColor?

strokeColor

public let strokeColor: PDFColor?

strokeWidth

public let strokeWidth: Double?

PDFSearchMatch

public struct PDFSearchMatch: Hashable, Sendable

page

public let page: Int

rects

public let rects: [CGRect]

PDFFormField

public struct PDFFormField: Hashable, Sendable

A form field of the document.

name

public let name: String

kind

public let kind: Kind

page

public let page: Int

frame

public let frame: CGRect

value

public let value: String

isChecked

public let isChecked: Bool?

exportValue

public let exportValue: String?

options

public let options: [String]

isReadOnly

public let isReadOnly: Bool

PDFMetadataKey

public enum PDFMetadataKey: String, Sendable, CaseIterable

title

case title = "Title", author = "Author", subject = "Subject", keywords = "Keywords"

creator

case creator = "Creator", producer = "Producer"

PDFFontFamily

public enum PDFFontFamily: Int32, Sendable

The built-in families every PDF reader has.

PDFZOrder

public enum PDFZOrder: Int32, Sendable

PDFMarkupKind

public enum PDFMarkupKind: Int32, Sendable

PDFImageKind

public enum PDFImageKind: Int32, Sendable

What an image layer is to the editor: a signature, a hand drawing and a stamp are images it knows by kind.

PDFFormFieldKind

public enum PDFFormFieldKind: Int32, Sendable

PDFTextResult

public enum PDFTextResult: Sendable

How a text replacement went.

replaced

case replaced

Replaced, and it fits where the old text was.

overflow

case overflow

Replaced, but taller than the old text (it may run into what is below it).

PDFDocumentError

public enum PDFDocumentError: Error, Equatable, Sendable

cannotOpen

case cannotOpen

The data is not a PDF this engine can open (or the password is wrong).

notFound

case notFound

No layer, page or field by that address (it may have been deleted — read the layers again).

unsupportedGlyphs

case unsupportedGlyphs

No font can draw some of the characters; NOTHING was changed. Give the editor a font that can.

failed

case failed(String)

The engine refused the change (wrong kind of layer, bad value, …).

PDFDocumentEditor

public final class PDFDocumentEditor

perform

public func perform(
    _ op: String,
    _ args: [String: Any] = [:],
) throws -> Any?

Run one document operation for a binding. See the file header for the conventions.

bridgeOpen

public static func bridgeOpen(
    _ data: Data,
    password: String?,
) throws -> PDFDocumentEditor

Open a document for a binding: PDFDocumentEditor(data:password:) with bridge errors.

init

public init(data: Data, password: String? = nil) throws

Open a PDF headless (no UI).

init

public convenience init(url: URL, password: String? = nil) throws

Open a PDF file headless (no UI).

pageCount

public var pageCount: Int

pageSize

public func pageSize(_ page: Int) throws -> CGSize

The page's size in points (as displayed, i.e. after its rotation).

save

public func save() throws -> Data

The edited PDF.

metadata

public func metadata(_ key: PDFMetadataKey) -> String

setMetadata

public func setMetadata(_ key: PDFMetadataKey, _ value: String)

Written into the file save() produces.

text

public func text(page: Int) -> String

The page's plain text.

search

public func search(
    _ query: String,
    caseSensitive: Bool = false,
) -> [PDFSearchMatch]

Every match of query in the document.

renderPage

public func renderPage(_ page: Int, size: CGSize) -> UIImage?

The page drawn into an image size pixels big (a thumbnail, a preview, a server-side render).

canUndo

public var canUndo: Bool

canRedo

public var canRedo: Bool

undo

@discardableResult public func undo() -> Bool

Undo the last change, the user's or this API's. A layer that comes back gets a NEW id — read the layers again.

redo

@discardableResult public func redo() -> Bool

insertBlankPage

public func insertBlankPage(at index: Int, size: CGSize = .zero) throws

Insert a blank page at index (a zero size takes the neighbouring page's).

deletePage

public func deletePage(_ index: Int) throws

movePage

public func movePage(from: Int, to: Int) throws

duplicatePage

public func duplicatePage(_ index: Int) throws

rotatePage

public func rotatePage(_ index: Int, clockwise: Bool = true) throws

importPages

public func importPages(
    from data: Data,
    password: String? = nil,
    pages: [Int]? = nil,
    at index: Int? = nil,
) throws

Copy pages (all when nil) of another PDF into this one at index (nil = the end). This starts the undo history afresh, as a flatten does, and layer ids must be read again.

extractPages

public func extractPages(_ pages: [Int]) throws -> Data

pages of this document as a new PDF.

layers

public func layers(page: Int) -> [PDFLayer]

Every layer of the page, in reading order (top to bottom, then left to right) for a page read the first time.

textBlocks

public func textBlocks(page: Int) -> [PDFLayer]

layer

public func layer(_ layer: PDFLayer) throws -> PDFLayer

The layer as it is now.

image

public func image(of layer: PDFLayer) -> UIImage?

The picture of an image layer, at its own pixel size.

sound

public func sound(of layer: PDFLayer) -> Data?

The audio of a sound layer.

setText

public func setText(
    _ layer: PDFLayer,
    _ text: String,
    shrinkToFit: Bool = false,
) throws -> PDFTextResult

Replace a text layer's text, keeping its font, size, colour and position. A paragraph re-wraps at its own width; a single line may grow to the page margin. shrinkToFit lowers the size (to half at most) until the text is no taller than before. Any script works: the system's fonts fill in what the layer's font lacks.

setFontSize

public func setFontSize(_ layer: PDFLayer, _ points: Double) throws

setFont

public func setFont(
    _ layer: PDFLayer,
    family: PDFFontFamily,
    bold: Bool = false,
    italic: Bool = false,
) throws

setFont

public func setFont(_ layer: PDFLayer, data: Data, name: String) throws

Embed a font of your own (TTF/OTF bytes) and set the layer in it.

setTextStyle

public func setTextStyle(
    _ layer: PDFLayer,
    bold: Bool? = nil,
    italic: Bool? = nil,
) throws

Bold / italic of the current family; nil leaves that one as it is.

setUnderline

public func setUnderline(_ layer: PDFLayer, _ on: Bool) throws

setStrikethrough

public func setStrikethrough(_ layer: PDFLayer, _ on: Bool) throws

setFillColor

public func setFillColor(_ layer: PDFLayer, _ color: PDFColor) throws

Text colour, or a shape's fill.

setStrokeColor

public func setStrokeColor(_ layer: PDFLayer, _ color: PDFColor) throws

setStrokeWidth

public func setStrokeWidth(_ layer: PDFLayer, _ points: Double) throws

setOpacity

public func setOpacity(_ layer: PDFLayer, _ opacity: Double) throws

setFrame

public func setFrame(_ layer: PDFLayer, _ frame: CGRect) throws

Move and resize (text scales uniformly).

setRotation

public func setRotation(_ layer: PDFLayer, _ degrees: Double) throws

Degrees, clockwise as seen.

setZOrder

public func setZOrder(_ layer: PDFLayer, _ order: PDFZOrder) throws
public func setLink(_ layer: PDFLayer, _ url: URL?) throws

nil removes the link.

setSound

public func setSound(
    _ layer: PDFLayer,
    _ audio: Data,
    name: String,
) throws

replaceImage

public func replaceImage(_ layer: PDFLayer, with image: UIImage) throws

Swap an image layer's picture, keeping its frame and kind.

setMarkup

public func setMarkup(
    _ layer: PDFLayer,
    _ kind: PDFMarkupKind,
    color: PDFColor,
) throws

Mark a whole text layer up.

removeMarkup

public func removeMarkup(_ layer: PDFLayer) throws

Remove a text layer's highlight / strikeout / squiggly.

delete

public func delete(_ layer: PDFLayer) throws

duplicate

@discardableResult public func duplicate(
    _ layer: PDFLayer,
    offset: CGSize = CGSize(width: 12, height: 12),
) throws -> PDFLayer

A copy offset by offset points.

copy

@discardableResult public func copy(
    _ layer: PDFLayer,
    toPage page: Int,
    at origin: CGPoint,
) throws -> PDFLayer

A copy on another page, its top-left at origin there.

addText

public func addText(
    _ text: String,
    page: Int,
    at origin: CGPoint,
    fontSize: Double = 14,
    color: PDFColor = .black,
    family: PDFFontFamily = .sans,
) throws -> PDFLayer

A text layer with its top-left at origin.

addImage

public func addImage(
    _ image: UIImage,
    page: Int,
    frame: CGRect,
    kind: PDFImageKind = .photo,
    note: String? = nil,
) throws -> PDFLayer

An image layer filling frame. A signature, a hand drawing or a stamp is an image of that kind.

addShape

public func addShape(
    _ shape: PDFLayer.Shape,
    page: Int,
    from start: CGPoint,
    to end: CGPoint,
    fill: PDFColor = .clear,
    stroke: PDFColor = .black,
    strokeWidth: Double = 2,
) throws -> PDFLayer

A rectangle or ellipse filling the rect from start to end, or a line / arrow from start to end.

markupText

public func markupText(
    page: Int,
    from start: CGPoint,
    to end: CGPoint,
    kind: PDFMarkupKind = .highlight,
    color: PDFColor = PDFColor(rgba: 0xFFE44DFF),
) throws

Mark up the text between two points of the page, as a drag with the tool would.

formFields

public func formFields() -> [PDFFormField]

setFormValue

public func setFormValue(_ value: String, forField name: String) throws

Fill a field: its text, an option's label, "true"/"false" for a check box, or the export value of the radio button to turn on.

fillForm

public func fillForm(_ values: [String: String]) throws

Fill several fields at once.

addFormField

public func addFormField(
    _ kind: PDFFormFieldKind,
    page: Int,
    frame: CGRect,
    name: String? = nil,
    options: [String] = [],
) throws -> String

A new field; returns its name (name, or one the editor made up). Radios that share a name are one set.

deleteFormField

public func deleteFormField(_ name: String) throws

Remove every widget called name (a whole radio set).

resetForm

public func resetForm() throws

flattenForm

public func flattenForm() throws

Bake the fields into the pages (their values stay, they stop being editable).

PDFLayer.Kind

public enum Kind: String, Sendable

PDFLayer.Shape

public enum Shape: String, Sendable

PDFFormField.Kind

public enum Kind: String, Sendable

SDK, licensing and callbacks

PDFEditorLicense

public struct PDFEditorLicense: Sendable, Equatable, CustomStringConvertible

The license verdict the SDK is running under.

status

public let status: Status

isLicensed

public let isLicensed: Bool

True when the editor may open documents (valid or development).

reason

public let reason: String

One sentence explaining status.

licensee

public let licensee: String

From the key (empty when there is none or it did not verify).

licenseID

public let licenseID: String

plan

public let plan: String

expires

public let expires: String?

YYYY-MM-DD, or nil for a key that does not expire.

updatesUntil

public let updatesUntil: String?

YYYY-MM-DD: the last SDK release date the key covers, or nil for every release.

platform

public let platform: String

What the SDK checked: "ios" or "macos", and the bundle identifier it read.

identity

public let identity: String

isOnline

public var isOnline: Bool = false

True for an online key (confirmed with the vendor's license server).

paymentDue

public var paymentDue: Bool = false

Online keys: the vendor marked the license's payment as overdue. It still works.

confirmedUntil

public var confirmedUntil: Date? = nil

Online keys: until when the current confirmation lets the app work offline (nil when there is none).

message

public var message: String = ""

Online keys: the vendor's note to the developer, if any.

description

public var description: String

PDFEditorSDK

public enum PDFEditorSDK

licenseDidChangeNotification

public static let licenseDidChangeNotification = Notification.Name("PDFEditorSDKLicenseDidChange")

Posted on the main queue after setLicenseKey(_:) runs, and when an online key's confirmation changes the verdict.

setLicenseKey

public static func setLicenseKey(_ key: String?) -> PDFEditorLicense

Set (or with nil clear) this app's license key. Returns the resulting verdict. Thread-safe; call it once at launch — application(_:didFinishLaunchingWithOptions:) or your App.init. For an online key the verdict may still be verificationRequired here, on the very first launch; the SDK confirms it in the background and posts licenseDidChangeNotification (an editor opened meanwhile waits for it).

refreshLicense

public static func refreshLicense() async -> PDFEditorLicense

Online keys: ask the license server now (the SDK also does it at launch and on returning to the foreground). Returns the verdict afterwards; offline keys return at once.

license

public static var license: PDFEditorLicense

The current license verdict.

version

public static let version: String = "2.4.1"

The released version of this SDK, matching the git tag consumers resolve (e.g. 1.13.0).

PDFEditorLicense.Status

public enum Status: String, Sendable, Codable

valid

case valid

The key covers this app.

development

case development

A valid key on a development host (only the web SDK uses this).

unlicensed

case unlicensed

No key has been set. Locked.

invalid

case invalid

The key is malformed, altered, or was not issued by the vendor. Locked.

expired

case expired

The key's expiry date has passed. Locked.

wrongApp

case wrongApp

The key does not name this app's bundle identifier. Locked.

wrongPlatform

case wrongPlatform

The key names no apps on this platform (iOS or macOS). Locked.

versionNotCovered

case versionNotCovered

This SDK release is newer than the key's "updates until" date. Locked.

unknownSigningKey

case unknownSigningKey

The key was issued under a signing key this SDK release does not know (update the SDK). Locked.

suspended

case suspended

An online key the vendor has suspended. Locked until they resume it.

verificationRequired

case verificationRequired

An online key not confirmed with the license server yet, or whose confirmation ran out. Locked until the app reaches the server.