Blog Post

Creating a PDF in Swift Using PDFKit

Illustration: Creating a PDF in Swift Using PDFKit

PDF is one of the most popular file formats in the world, and viewing PDF files is supported on almost all devices and operating systems out of the box. In the past, we talked about the different ways to create a PDF on iOS. One such way is with the PDFKit framework from Apple, which has been available since iOS 11 and allows for configuring the metadata of a PDF document and customizing the PDF by adding widgets and annotations.

In this tutorial, you’ll learn how to use the basics of PDFKit to configure and modify a PDF document. First, you’ll see how to work with Core Graphics to create a PDF. Then, you’ll learn how you can display a PDF with PDFKit. Lastly, you’ll find out how to add annotations and write changes to the PDF.

Creating a PDF with PDFKit

The metadata information for a PDF has to be set while generating the PDF context for its creation. There’s a set of auxiliary dictionary keys that are part of the PDF, and these keys are used to specify the metadata for the PDF. It’s important to note that PDFKit doesn’t allow creating a PDF, and as such, Core Graphics needs to be used:

let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let filePath = (documentsDirectory as NSString).appendingPathComponent("foo.pdf") as String

let pdfTitle = "Swift-Generated PDF"
let pdfMetadata = [
    // The name of the application creating the PDF.
    kCGPDFContextCreator: "Your iOS App",

    // The name of the PDF's author.
    kCGPDFContextAuthor: "Foo Bar",

    // The title of the PDF.
    kCGPDFContextTitle: "Lorem Ipsum",

    // Encrypts the document with the value as the owner password. Used to enable/disable different permissions.
    kCGPDFContextOwnerPassword: "myPassword123"
]

// Creates a new PDF file at the specified path.
UIGraphicsBeginPDFContextToFile(filePath, CGRect.zero, pdfMetadata)

// Creates a new page in the current PDF context.
UIGraphicsBeginPDFPage()

// Default size of the page is 612x72.
let pageSize = UIGraphicsGetPDFContextBounds().size
let font = UIFont.preferredFont(forTextStyle: .largeTitle)

// Let's draw the title of the PDF on top of the page.
let attributedPDFTitle = NSAttributedString(string: pdfTitle, attributes: [NSAttributedString.Key.font: font])
let stringSize = attributedPDFTitle.size()
let stringRect = CGRect(x: (pageSize.width / 2 - stringSize.width / 2), y: 20, width: stringSize.width, height: stringSize.height)
attributedPDFTitle.draw(in: stringRect)

// Closes the current PDF context and ends writing to the file.
UIGraphicsEndPDFContext()

Since the annotated Core Foundation APIs are automatically memory-managed in Swift, you don’t have to be concerned with the manual retaining and releasing of objects here. Apart from these basic keys, there are other keys that can be used to create the metadata for a PDF.

Viewing a PDF

The traditional approach for viewing a PDF is to open it in a web view. But you can leverage the PDFKit framework to view PDF documents in your apps:

// Don't forget to import the PDFKit framework.
import PDFKit

// ....
// ....

// Create and add a `PDFView` to the view hierarchy.
let pdfView = PDFView(frame: view.bounds)
pdfView.autoscales = true
view.addSubview(pdfView)

// Create a `PDFDocument` object and set it as `PDFView`'s document to load the document in that view.
let pdfDocument = PDFDocument(url: URL(fileURLWithPath: filePath))!
pdfView.document = pdfDocument

Modifying a PDF

PDFKit can also be used to modify the contents of a PDF, like so:

// Adding an annotation.
let squareAnnotation = PDFAnnotation(bounds: CGRect(x: 200, y: 100, width: 100, height: 100), forType: PDFAnnotationSubtype.square, withProperties: nil)
squareAnnotation.color = UIColor.blue
let page = pdfDocument.page(at: 0)!
page.addAnnotation(squareAnnotation)

// Writing the changes to the file.
pdfDocument.write(toFile: self.filePath)

One thing that needs to be considered is that the coordinate system of a PDF is different than that of the views: The origin of the coordinates in a PDF is in the bottom-left corner, instead of top-left corner like in the views.

PDFKit has methods on PDFView to convert the coordinates to the PDF space, but there’s one issue with them, which is that if the bounds of the PDFView are bigger than that of the page size in the document, you could end up making changes outside the bounds of the drawn page and losing your content.

Conclusion

This blog post covered how to create and modify a PDF in Swift using PDFKit. While it’s relatively easy to do, the PDFKit framework was only introduced in 2017, and it still lacks some features that certain users might require. Another downside of using PDFKit is that the framework update frequency isn’t too high, meaning that the introduction of newer features and fixing of existing bugs could take some time.

Our iOS PDF SDK, on the other hand, is a feature-rich, battle-tested framework trusted by some of the largest companies in the world. Below is an example comparison of how a PDF appears using PDFView and PSPDFKit.

<code>PDFView</code> and PSPDFKit comparison

PSPDFKit supports customizing the PDF rendering style, allows generating PDF reports, and much more. It includes numerous example projects, which help you set up the SDK with your project. We’re always improving the framework, fixing issues, and releasing updates regularly to ensure the best possible experience for the user.

Try our Swift PDF library using our free trial, and check out our demos to see what’s possible. If you’ve been using PDFKit and want to switch, we also have a guide for migrating to PSPDFKit.

Free 60-Day Trial Try PSPDFKit in your app today.
Free Trial

Related Articles

Explore more
TUTORIALS  |  iOS • How To • Signing • PDF

How to Digitally Sign a PDF Using a YubiKey

BLOG  |  iOS • Instant • Products

Using Instant Layers for Onsite Visits

DEVELOPMENT  |  iOS • Development

Fitting Text into a Bounding Frame on iOS