Generación de informes PDF en Swift para iOS y macOS
La creación de documentos PDF es una de las tareas comunes en aplicaciones móviles y de escritorio. En las plataformas de Apple (iOS, macOS) hay potentes herramientas integradas disponibles para esto: PDFKit y Core Graphics. En este artículo, analizaremos cómo generar un informe de varias páginas con tablas, texto y gráficos, utilizando solo Swift nativo.
¿Por qué usar las herramientas integradas?
- No requiere dependencias de terceros — todo ya está incluido en el SDK.
- Control total sobre la representación — trabajo con coordenadas, fuentes, colores.
- Multiplataforma — el código funciona tanto en iOS como en macOS.
- Alto rendimiento — Core Graphics utiliza aceleración por hardware.
Enfoques principales
Existen dos formas principales de generar PDF en Swift:
- PDFKit — API de alto nivel para trabajar con PDF (lectura, edición, creación).
- Core Graphics — representación de bajo nivel a través del contexto PDF.
Analizaremos el segundo enfoque, ya que ofrece la máxima flexibilidad al crear informes «desde cero».
Creación del contexto PDF
El primer paso es crear un contexto PDF en el que dibujaremos los elementos. Para esto se utiliza la función UIGraphicsBeginPDFContextToFile (iOS) o su 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) // Aquí dibujaremos las páginas UIGraphicsEndPDFContext() return pdfURL}Añadir páginas y contenido
Cada página comienza con la llamada a UIGraphicsBeginPDFPage(). Después de eso, se pueden usar los métodos estándar de UIKit para dibujar.
func drawReport() { guard let pdfURL = generatePDF() else { return } UIGraphicsBeginPDFContextToFile(pdfURL.path, CGRect(x: 0, y: 0, width: 612, height: 792), nil) // Primera página UIGraphicsBeginPDFPage() drawHeader(title: "Informe mensual") drawTable(data: sampleData) // Segunda página (si es necesario) UIGraphicsBeginPDFPage() drawChart() UIGraphicsEndPDFContext()}Dibujar texto y encabezados
Para dibujar texto usamos NSString con 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)}Crear una tabla simple
La tabla se puede dibujar usando líneas y texto. A continuación, un ejemplo de generación de una tabla con dos columnas.
func drawTable(data: [(String, String)]) { let startX: CGFloat = 50 var startY: CGFloat = 100 let colWidth: CGFloat = 250 let rowHeight: CGFloat = 30 // Dibujar encabezados let headerAttributes: [NSAttributedString.Key: Any] = [ .font: UIFont.boldSystemFont(ofSize: 14), .foregroundColor: UIColor.black ] "Nombre".draw(at: CGPoint(x: startX, y: startY), withAttributes: headerAttributes) "Valor".draw(at: CGPoint(x: startX + colWidth, y: startY), withAttributes: headerAttributes) startY += rowHeight // Dibujar filas for (key, value) in data { let rowAtt