PDF генерация в Swift: создание документов для iOS и macOS

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

PDF генерация в Swift (iOS/macOS): полное руководство

Создание PDF-документов — одна из частых задач в iOS и macOS приложениях: от формирования отчётов и счетов до экспорта данных и создания электронных книг. В Swift для этого существует несколько встроенных и сторонних инструментов. В этой статье мы подробно разберём основные подходы к генерации PDF на платформах Apple, их возможности и примеры использования.

Встроенные фреймворки Apple

Экосистема Apple предоставляет мощные инструменты для работы с PDF без сторонних зависимостей. Основные из них:

  • UIGraphicsPDFRenderer (iOS 10+) — современный API для создания PDF в UIKit.
  • PDFKit — фреймворк для отображения, редактирования и создания PDF (доступен на iOS 11+ и macOS 10.13+).
  • Core Graphics (Quartz 2D) — низкоуровневый C-based API для рисования и генерации PDF.

1. UIGraphicsPDFRenderer — простой и быстрый старт

Это самый удобный способ для iOS. Он позволяет создавать многостраничный PDF, рисуя с помощью UIKit (UIView, UIImage, текст и т.д.).

import UIKit

func generatePDF() -> Data? {
    let pageSize = CGRect(x: 0, y: 0, width: 595.2, height: 841.8) // A4
    let renderer = UIGraphicsPDFRenderer(bounds: pageSize)

    let data = renderer.pdfData { context in
        context.beginPage()

        // Рисуем текст
        let text = "Привет, мир PDF!"
        let attributes: [NSAttributedString.Key: Any] = [
            .font: UIFont.systemFont(ofSize: 24),
            .foregroundColor: UIColor.black
        ]
        text.draw(at: CGPoint(x: 50, y: 100), withAttributes: attributes)

        // Рисуем изображение
        if let image = UIImage(named: "logo") {
            image.draw(in: CGRect(x: 50, y: 200, width: 200, height: 100))
        }

        // Вторая страница
        context.beginPage()
        let text2 = "Это вторая страница"
        text2.draw(at: CGPoint(x: 50, y: 50), withAttributes: attributes)
    }

    return data
}

// Сохранение в файл
if let pdfData = generatePDF() {
    let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let pdfURL = documentsPath.appendingPathComponent("document.pdf")
    try? pdfData.write(to: pdfURL)
    print("PDF сохранён: \(pdfURL)")
}

2. PDFKit — для продвинутой работы с документами

PDFKit предоставляет классы PDFDocument и PDFPage. Он идеален для создания PDF из текста с форматированием, таблиц и изображений. Поддерживает работу с аннотациями, закладками и формами.

import PDFKit

func createPDFWithPDFKit() -> PDFDocument {
    let document = PDFDocument()

    // Создаём страницу через NSAttributedString
    let pageRect = CGRect(x: 0, y: 0, width: 612, height: 792) // US Letter
    let text = NSAttributedString(string: "Пример PDF с PDFKit\nВторая строка")
    let page = PDFPage()

    // Рендеринг в контекст страницы
    let renderer = UIGraphicsImageRenderer(bounds: pageRect)
    let image = renderer.image { ctx in
        text.draw(at: CGPoint(x: 72, y: 72))
    }

    // Создаём страницу из изображения (упрощённо)
    // В реальном проекте используйте PDFPage с drawBlock
    let finalPage = PDFPage(image: image) ?? PDFPage()
    document.insert(finalPage, at: 0)

    return document
}

// Сохранение
if let document = createPDFWithPDFKit() as? PDFDocument {
    let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("pdfkit_example.pdf")
    document.write(to: url)
}

Важно: PDFKit доступен только на iOS 11+/macOS 10.13+. Для более старых версий используйте UIGraphicsPDFRenderer.

3. Core Graphics (Quartz 2D) — максимальный контроль

Если вам нужен полный контроль над каждым пикселем, используйте Core Graphics. Это низкоуровневый C-API, но Swift-обёртка делает его удобным.

import CoreGraphics

func createPDFWithCoreGraphics(url: URL) {
    let pageRect = CGRect(x: 0, y: 0, width: 612, height: 792)
    let consumer = CGDataConsumer(url: url as CFURL)!
    let context = CGContext(consumer: consumer, mediaBox: &pageRect, nil)!

    // Начинаем документ
    context.beginPDFPage(nil)

    // Рисуем текст
    let text = "Core Graphics PDF" as CFString
    let font = CTFontCreateWithName("Helvetica" as CFString, 24, nil)
    let attributes = [kCTFontAttributeName: font]                    

Рекомендаций