iOS PDFKit: creating PDF document in Swift, inserting/deleting pages
Tags: ios, swift, pdfkit
Published: 2023-03-19 13:44:24

This is the third article about Apple’s PDFkit featuring in-code document creation and pages operations.

- [First](https://dev.to/artem_poluektov/ios-pdfkit-ink-annotations-tutorial-4kgh) article is about PDFKit basics & Ink annotations
- [Second](https://dev.to/artem_poluektov/ios-pdfkit-tutorial-text-annotations-more-bc7) is about PencilKit, Text annotations & auto-saving

## Create PDF Document using Swift

In case you need to create a new PDF file on iOS device you won’t actually need to use PDFKit at all. There are few simple UIKit methods for that.

First, you need to create `UIGraphicsPDFRendererFormat` object to provide PDF document metadata such as author, etc.
```
let format = UIGraphicsPDFRendererFormat()
let metaData = [
    kCGPDFContextTitle: "Hello, World!",
    kCGPDFContextAuthor: "John Doe"
  ]
format.documentInfo = metaData as [String: Any]
```
You’ll find a full list of available metadata parameters in CoreGraphics framework reference documentation, just start typing `kCGPDF` in your code in Xcode.

Second, we need to calculate PDF page dimensions. PDF documents use a default resolution of 72 DPI. Page dimensions would be:

```
// US Letter
Width: 8.5 inches * 72 DPI = 612 points
Height: 11 inches * 72 DPI = 792 points
// A4 would be [W x H] 595 x 842 points
```
After doing this math, we need to instantiate `UIGraphicsPDFRenderer` object, which is responsible of document rendering.

```
let pageRect = CGRect(x: 0, y: 0, width: 595, height: 842)
let renderer = UIGraphicsPDFRenderer(bounds: pageRect,
                                     format: format)
```
Third, to start drawing just call .pdfData method of your renderer:
```
let data = renderer.pdfData { (context) in
// Perform your drawing here
}
```
You could call every drawing method of `CoreGraphics` framework here. But, first you need to create new PDF page by calling `context.beginPage()`. Call this code every time you need to start new page.
To draw a simple “Hello, world!” text use this code example:

```
let data = renderer.pdfData { (context) in
  context.beginPage()
  
  let paragraphStyle = NSMutableParagraphStyle()
  paragraphStyle.alignment = .center
  let attributes = [
    NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 14),
    NSAttributedString.Key.paragraphStyle: paragraphStyle
  ]
  let text = "Hello, World!"
  let textRect = CGRect(x: 100, // left margin
                        y: 100, // top margin
                    width: 200,
                   height: 20)

  text.draw(in: textRect, withAttributes: attributes)
}
```
What’s just happened?

- We started new PDF page.
- Created new `NSParagraphStyle` object to add `.center` alignment to our text.
- Created `attributes` dictionary containing font and paragraph style.
- Created text String.
- Created `textRect` struct describing specific rect where our text would be drawn.
- Called `.draw` method of string object.

That’s it. Easy, right? Just provide your own attributes like color, font, etc.

Finally, we must save out PDF context to file on device. As rendered would return `Data` object, we have 2 ways of saving our document:

- Initializing `PDFKit`'s `PDFDocument(data:)` object and writing it to file
```
let pdfDocument = PDFDocument(data: data)
let path = PATH_TO_DESIRED_FILE
pdfDocument.write(to: path)
```

- Using `UIGraphicsPDFRendered`'s method `writePDF` instead of `pdfData` in third step. Let's replace

```
let data = renderer.pdfData { (context) in
```
with

```
let url = URL_TO_DESIRED_FILE
try? rendered.writePDF(to: url) { (context) in
  ...
}
```
You must add `try?` call because writing operation is throwable.

---

## Insert page to PDF document

To add or remove pages to/from PDF document we need to use Apple’s `PDFKit` methods.
First, you need to initialize 2 PDF documents. One where the page would be inserted, and another from which we’ll take the page to insert.

```
let firstPDFDocument = PDFDocument(url: URL_TO_YOUR_FIRST_DOC)
let secondPDFDocument = PDFDocument(url: URL_TO_YOUR_SECOND_DOC)
```
Second, locate the page you want to insert and insert it at desired location:

```
// let's assume we want to insert 5th page of 2nd doc to 1st doc
let page = secondDocument.page(at: 5)
// And insert this page as first
firstDocument.insert(page, at: 0)
```
Don’t forget to save your document after insertion:

```
firstDocument.write(to: URL_TO_YOUR_FIRST_DOC)
```

---

## Remove page from PDF Document

Removing pages is easy as well:

```
let pdfDocument = PDFDocument(url: URL_TO_YOUR_DOC)
pdfDocument.removePage(at: 0) // removing the first page
firstDocument.write(to: URL_TO_YOUR_DOC)
```
That’s it.