PDF Generation in Swift (iOS/macOS): Complete Guide
Creating PDF documents is one of the key tasks when developing applications for iOS and macOS. Reports, invoices, certificates, e-books — all of this requires a reliable and flexible tool for PDF generation. In the Swift ecosystem, there are several approaches: from Apple's built-in frameworks to third-party libraries with advanced capabilities. In this article, we will cover the main methods of PDF generation, their advantages and disadvantages, and provide working code examples.
1. PDFKit — Apple's Built-in Framework
PDFKit is a powerful framework from Apple, available on iOS 11+ and macOS 10.13+. It provides a high-level API for creating, displaying, and editing PDF documents. Key features:
- Creating PDF from UIView, UIImage, or text
- Adding annotations, forms, and hyperlinks
- Working with multi-page documents
- Support for Core Graphics for custom drawing
Example of creating a PDF from UIView:
import PDFKit
func generatePDF(from view: UIView) -> Data? { let pdfData = NSMutableData() UIGraphicsBeginPDFContextToData(pdfData, view.bounds, nil) UIGraphicsBeginPDFPage() guard let context = UIGraphicsGetCurrentContext() else { return nil } view.layer.render(in: context) UIGraphicsEndPDFContext() return pdfData as Data}This method is suitable if you need to quickly "snapshot" an existing interface. However, for complex layouts (tables, headers/footers, custom fonts), it's better to use Core Graphics directly.
2. Core Graphics (Quartz 2D) — Low-Level Solution
Core Graphics gives you full control over the drawing process. You work with the PDF context, draw lines, text, images, and manage pages. This is the most flexible but also the most labor-intensive method.
Example of creating a simple PDF with text:
import UIKit
func createPDFWithText() -> Data? { let pageSize = CGRect(x: 0, y: 0, width: 612, height: 792) // A4 let data = NSMutableData() UIGraphicsBeginPDFContextToData(data, pageSize, nil) UIGraphicsBeginPDFPage() guard let context = UIGraphicsGetCurrentContext() else { return nil } let text = "Hello, PDF World!" let attributes: [NSAttributedString.Key: Any] = [ .font: UIFont.systemFont(ofSize: 24), .foregroundColor: UIColor.black ] text.draw(at: CGPoint(x: 50, y: 50), withAttributes: attributes) UIGraphicsEndPDFContext() return data as Data}For complex documents (tables, images, page numbering), you'll have to write a lot of helper code. However, you get maximum performance and minimal file size.
3. TPPDF — Third-Party Open Source Library
TPPDF (GitHub: techprimate/TPPDF) is a Swift library for PDF generation with a declarative syntax. It supports:
- Text, images, tables, lists
- Headers/footers, page numbering
- Automatic content flow between pages
- Custom fonts, colors, borders
Installation via Swift Package Manager:
// Package.swiftdependencies: [ .package(url: "https://github.com/techprimate/TPPDF.git", from: "2.0.0")]Example of creating a document with a table:
import TPPDF
func generateInvoice() -> Data? { let document = PDFDocument(format: .a4) // Add a title document.add(text: "Invoice No. 123", style: PDFTextStyle.heading1) // Create a table let table = PDFTable(rows: 3, columns: 2) table[0][0].content = "Product" table[0][1].content = "Price" table[1][