Geração de relatórios PDF em Swift (iOS/macOS) com PDFKit
Criar documentos PDF é uma das tarefas comuns em aplicativos móveis e desktop. Nas plataformas Apple (iOS, macOS, watchOS, tvOS), o framework integrado PDFKit é usado para isso. Ele permite gerar, exibir e editar arquivos PDF programaticamente. Neste artigo, veremos como criar um relatório PDF completo em Swift: com texto, tabelas, imagens e páginas personalizáveis.
O que é PDFKit?
PDFKit é um framework da Apple que faz parte dos SDKs padrão do iOS/macOS. Ele fornece classes para trabalhar com PDF:
PDFDocument— representação de todo o documento.PDFPage— uma página individual.PDFView— exibição de PDF na tela.UIPrintPageRenderer(para iOS) — geração de páginas através de desenho Core Graphics.
Para gerar relatórios, geralmente usamos UIPrintPageRenderer ou desenhamos diretamente com Core Graphics no contexto PDF. O segundo método oferece mais flexibilidade, mas requer mais código.
Preparação do projeto
Abra o Xcode, crie um novo projeto para iOS ou macOS. Certifique-se de importar o módulo PDFKit:
import PDFKitimport UIKit // para iOSPara macOS, será necessário import Cocoa e o trabalho correspondente com NSView.
Método 1: Geração de PDF via UIPrintPageRenderer (iOS)
Este método é conveniente se você deseja usar marcação HTML ou layouts complexos. UIPrintPageRenderer permite renderizar páginas através de UIPrintFormatter.
func generatePDFUsingRenderer() -> Data? { let renderer = UIPrintPageRenderer() // Configuração do tamanho da página A4 let pageSize = CGRect(x: 0, y: 0, width: 595.2, height: 841.8) // em pontos renderer.setValue(pageSize, forKey: "paperRect") renderer.setValue(pageSize, forKey: "printableRect") // Cria uma string HTML com o relatório let htmlString = """ <h1>Relatório de Vendas</h1> <p>Data: 2025-03-17</p> <table border="1"> <tr><th>Produto</th><th>Quantidade</th><th>Preço</th></tr> <tr><td>Notebook</td><td>5</td><td>50000</td></tr> <tr><td>Mouse</td><td>20</td><td>1500</td></tr> </table> """ let formatter = UIMarkupTextPrintFormatter(markupText: htmlString) renderer.addPrintFormatter(formatter, startingAtPageAt: 0) // Renderização em PDF let pdfData = NSMutableData() UIGraphicsBeginPDFContextToData(pdfData, .zero, nil) for pageIndex in 0..<renderer.numberOfPages { UIGraphicsBeginPDFPage() renderer.drawPage(at: pageIndex, in: UIGraphicsGetCurrentContext()!) } UIGraphicsEndPDFContext() return pdfData as Data}Chame a função e salve o resultado:
if let pdfData = generatePDFUsingRenderer() { let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) let fileURL = paths[0].appendingPathComponent("report.pdf") try? pdfData.write(to: fileURL) print("PDF salvo: \\(fileURL)")}Método 2: Desenho via Core Graphics (iOS/macOS)
Este método é de nível mais baixo, mas oferece controle total sobre cada elemento. É adequado para macOS, onde UIPrintPageRenderer não está disponível.
func generatePDFWithCoreGraphics() -> Data? { let pdfData = NSMutableData() let pageRect = CGRect(x: 0, y: 0, width: 612, height: 792) // US Letter guard let consumer = CGDataConsumer(data: pdfData), let pdfContext = CGContext(consumer: consu