Geração de relatórios PDF em Swift para iOS e macOS
Criar documentos PDF é uma das tarefas comuns em aplicativos móveis e desktop. Nas plataformas Apple (iOS, macOS), existem ferramentas nativas poderosas disponíveis: PDFKit e Core Graphics. Neste artigo, vamos abordar como gerar um relatório de várias páginas com tabelas, texto e gráficos, usando apenas Swift nativo.
Por que usar ferramentas nativas?
- Não requer dependências de terceiros — tudo já está incluído no SDK.
- Controle total sobre a renderização — trabalho com coordenadas, fontes e cores.
- Multiplataforma — o código funciona tanto no iOS quanto no macOS.
- Alto desempenho — Core Graphics usa aceleração de hardware.
Principais abordagens
Existem duas maneiras principais de gerar PDF em Swift:
- PDFKit — API de alto nível para trabalhar com PDF (leitura, edição, criação).
- Core Graphics — renderização de baixo nível através do contexto PDF.
Vamos abordar a segunda abordagem, pois oferece máxima flexibilidade ao criar relatórios "do zero".
Criando o contexto PDF
O primeiro passo é criar um contexto PDF, onde desenharemos os elementos. Para isso, usa-se a função UIGraphicsBeginPDFContextToFile (iOS) ou seu equivalente para macOS.
import UIKit
func generatePDF() -> URL? { let fileName = "Report.pdf" let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) guard let documentsURL = paths.first else { return nil } let pdfURL = documentsURL.appendingPathComponent(fileName) let pageSize = CGRect(x: 0, y: 0, width: 612, height: 792) // A4 UIGraphicsBeginPDFContextToFile(pdfURL.path, pageSize, nil) // Aqui desenharemos as páginas UIGraphicsEndPDFContext() return pdfURL}Adicionando páginas e conteúdo
Cada página começa com a chamada UIGraphicsBeginPDFPage(). Depois disso, você pode usar métodos padrão do UIKit para desenhar.
func drawReport() { guard let pdfURL = generatePDF() else { return } UIGraphicsBeginPDFContextToFile(pdfURL.path, CGRect(x: 0, y: 0, width: 612, height: 792), nil) // Primeira página UIGraphicsBeginPDFPage() drawHeader(title: "Relatório Mensal") drawTable(data: sampleData) // Segunda página (se necessário) UIGraphicsBeginPDFPage() drawChart() UIGraphicsEndPDFContext()}Desenhando texto e cabeçalhos
Para desenhar texto, usamos NSString com atributos.
func drawHeader(title: String) { let titleAttributes: [NSAttributedString.Key: Any] = [ .font: UIFont.boldSystemFont(ofSize: 24), .foregroundColor: UIColor.darkGray ] title.draw(at: CGPoint(x: 50, y: 40), withAttributes: titleAttributes)}Criando uma tabela simples
A tabela pode ser desenhada usando linhas e texto. Abaixo está um exemplo de geração de tabela com duas colunas.
func drawTable(data: [(String, String)]) { let startX: CGFloat = 50 var startY: CGFloat = 100 let colWidth: CGFloat = 250 let rowHeight: CGFloat = 30 // Desenha cabeçalhos let headerAttributes: [NSAttributedString.Key: Any] = [ .font: UIFont.boldSystemFont(ofSize: 14), .foregroundColor: UIColor.black ] "Nome".draw(at: CGPoint(x: startX, y: startY), withAttributes: headerAttributes) "Valor".draw(at: CGPoint(x: startX + colWidth, y: startY), withAttributes: headerAttributes) startY += rowHeight // Desenha linhas for (key, value) in data { let rowAtt