Contents

Custom Graphics

Demonstrates adding a watermark to a PDF page.

Overview

You can add a custom drawing to a page or annotation by overriding that class’s draw method. Adding drawings to pages can be useful for adding custom layered effects or, as shown in this sample, watermarking a document.

Register the Delegate and Set the Page Class

The UIViewController class first initializes a PDFDocument instance and sets its delegate to self.

// 1. Set delegate
document.delegate = self
pdfView?.document = document

The delegate, of type PDFDocumentDelegate, implements a classForPage() method. This method returns AnyClass and declares that all instances of PDFPage for the document presented through PDFView should instantiate the subclass WatermarkPage.

This subclass, found in WatermarkPage.swift, implements custom drawing.

// 2. Return your custom PDFPage class
/// - Tag: ClassForPage
func classForPage() -> AnyClass {
    return WatermarkPage.self
}

ViewController loads a URL to the Sample.pdf file through the app’s main bundle. This URL is then used to instantiate a PDFDocument. On success, the document is assigned to the PDFView, which was set up in Interface Builder.

The delegate is assigned before the document, so classForPage(), a PDFDocumentDelegate method, is implemented. This method returns the PDFPage subclass used for custom drawing.

Override the Draw Method

WatermarkPage subclasses PDFPage so that it can override the draw(with:to:) method. This method is called by PDFDocument to draw the page in a PDFView. All custom drawing for a PDF page should be done through this mechanism.

// 3. Override PDFPage custom draw
/// - Tag: OverrideDraw
override func draw(with box: PDFDisplayBox, to context: CGContext) {

    // Draw original content
    super.draw(with: box, to: context)

    // Draw rotated overlay string
    UIGraphicsPushContext(context)
    context.saveGState()

    let pageBounds = self.bounds(for: box)
    context.translateBy(x: 0.0, y: pageBounds.size.height)
    context.scaleBy(x: 1.0, y: -1.0)
    context.rotate(by: CGFloat.pi / 4.0)

    let string: NSString = "U s e r   3 1 4 1 5 9"
    let attributes: [NSAttributedString.Key: Any] = [
        NSAttributedString.Key.foregroundColor: #colorLiteral(red: 0.4980392157, green: 0.4980392157, blue: 0.4980392157, alpha: 0.5),
        NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 64)
    ]

    string.draw(at: CGPoint(x: 250, y: 40), withAttributes: attributes)

    context.restoreGState()
    UIGraphicsPopContext()

}

Custom drawing methods should always be thread-safe and call the superclass method, which is required to draw the original PDFPage content. Custom drawing code can execute before or after this superclass call, although order matters. If your graphics run before the superclass call, they’re drawn below the PDFPage content. Conversely, if your graphics run after the superclass call, they’re drawn above the PDFPage content.

See Also

Annotations