Core Graphics es el framework de renderizado 2D de Apple, parte de Core Foundation, disponible en iOS, macOS, tvOS y watchOS. Proporciona una API C de bajo nivel para trabajar con gráficos vectoriales y rasterizados, incluyendo dibujo de trazados, degradados, sombras, imágenes y texto. Core Graphics sirve como base para UIKit, SwiftUI y AppKit. Según Apple Developer Documentation, 2026, el framework se utiliza en más del 90% de las aplicaciones iOS, porque cada elemento visible pasa a través de Core Graphics o su equivalente hardware.
Puntos clave
Core Graphics (también conocido como Quartz 2D) es un framework que implementa el motor de gráficos 2D de Apple. Está basado en la biblioteca portátil de gráficos Quartz y utiliza un modelo de dibujo basado en páginas, donde cada acción es un comando en una secuencia similar a dibujar en papel. Core Graphics admite antialiasing, transparencia (composición alfa) y espacios de color ICC.
La arquitectura de Core Graphics se construye alrededor de un contexto gráfico (CGContext) que encapsula el dispositivo de salida objetivo: pantalla, impresora, documento PDF o búfer rasterizado. El contexto gestiona la configuración actual: color, grosor de línea, transformación, área de recorte y fuentes. Este enfoque proporciona una API uniforme para diferentes dispositivos de salida sin cambiar el código de dibujo.
Core Graphics funciona principalmente en la CPU, utilizando un modelo vectorial (independiente de la resolución). Esto significa que las líneas y curvas se rasterizan con la resolución actual del dispositivo al dibujarse. A diferencia de Metal, Core Graphics no requiere gestión explícita de recursos GPU — el sistema maneja toda la optimización. Para la mayoría de tareas 2D (gráficos, diagramas, elementos UI personalizados), el rendimiento de Core Graphics es suficiente para mantener 60 FPS.
Core Graphics incluye alrededor de 50 tipos base (tipos opacos), cada uno responsable de una funcionalidad específica. Todos los tipos siguen las reglas de gestión de memoria de Core Foundation: se crean mediante funciones con Create en el nombre, requieren una llamada a CGRelease y no son compatibles con ARC en Objective-C (sin embargo Swift gestiona la memoria automáticamente mediante anotaciones CF_RETURNS_RETAINED).
CGContext — el contexto de dibujo, el tipo central del framework. CGPath — un trazado vectorial inmutable. CGColor — un color con un espacio de color especificado. CGGradient — un relleno degradado. CGImage — una imagen rasterizada. CGLayer — un búfer offline optimizado para dibujo repetitivo. CGDataProvider — una fuente de datos para imágenes. CGColorSpace — un espacio de color (sRGB, Display P3, Gray).
Cada tipo está diseñado para una sobrecarga mínima: CGPath se puede almacenar en caché y reutilizar entre diferentes contextos, CGColor se convierte a representación hardware de GPU al pasarse, CGLayer almacena contenido prerasterizado. Esta arquitectura permite que Core Graphics funcione eficientemente tanto en tareas UI simples como en editores gráficos profesionales.
| Tipo | Propósito | Gestión de memoria |
|---|---|---|
| CGContext | Contexto gráfico | CFRelease o automático en Swift |
| CGPath | Trazado vectorial | CFRelease (inmutable) |
| CGColor | Color en espacio de color | CFRelease o CGColorCreate |
| CGImage | Imagen rasterizada | CFRelease (después de crear) |
| CGLayer | Búfer offline | CFRelease o CGLayerCreate |
CGPath es un objeto inmutable que describe una secuencia de segmentos geométricos: líneas rectas, curvas Bezier, arcos y cierres. A diferencia de UIBezierPath, CGPath no contiene métodos de dibujo — solo almacena la geometría. Para dibujar, CGPath se añade al contexto (CGContextAddPath) y luego se renderiza mediante strokePath o fillPath. La inmutabilidad garantiza seguridad en hilos y capacidad de almacenamiento en caché.
CGPathCreateMutable crea un trazado mutable (CGMutablePathRef) para construcción paso a paso. Después del ensamblaje final, se convierte en un CGPathRef inmutable. Apple recomienda minimizar el número de puntos en CGPath — los trazados demasiado complejos (más de 1000 segmentos) ralentizan la rasterización. Para optimizar, use CGPathCreateCopyBySimplifyingPath, que elimina puntos colineales redundantes.
Para animar la forma entre dos objetos CGPath, puede usar CABasicAnimation en la propiedad path de CAShapeLayer. Limitación: ambos CGPath deben tener el mismo número de segmentos (puntos de control). La función CGPathApply permite recorrer todos los elementos del trazado y comparar su estructura. Si los segmentos no coinciden, la animación será entrecortada — en este caso, use CADisplayLink para interpolación manual de puntos.
// crear trazado mutable
let mutablePath = CGMutablePath()
mutablePath.moveTo(to: CGPoint(x: 0, y: 0))
mutablePath.addLine(to: CGPoint(x: 100, y: 0))
mutablePath.addLine(to: CGPoint(x: 100, y: 100))
mutablePath.closeSubpath()
// convertir a inmutable para caché segura
let immutablePath: CGPath = mutablePath
CATransaction.perform {
shapeLayer.path = immutablePath
}
CGGradient es un objeto que define una transición suave entre dos o más colores a lo largo de una línea recta (degradado lineal) o del centro hacia los bordes (degradado radial). CGGradient se crea con un espacio de color especificado, un array de CGColorRef y un array de posiciones de parada de 0.0 a 1.0. Después de la creación, el degradado se puede reutilizar múltiples veces en diferentes contextos.
CGShading es un mecanismo más potente que permite definir una función de cambio de color a lo largo de un trazado. A diferencia de CGGradient, que trabaja con un conjunto fijo de colores, CGShading utiliza una función callback (CGFunctionRef) que calcula el color en cada punto. Esto permite crear degradados complejos con transiciones no lineales y esquemas de color compuestos.
Para dibujar un degradado dentro de una forma, se necesita un clip sobre el trazado de la forma. El orden: añadir el trazado al contexto, llamar a CGContextClip, luego dibujar el degradado. Sin un clip, el degradado llena todo el contexto. En iOS, se recomienda CGGradient como la opción más simple y eficiente — CGShading solo se justifica para funciones de color personalizadas.
func drawGradient(ctx: CGContext, rect: CGRect) {
let colors = [UIColor.red.cgColor, UIColor.blue.cgColor] as CFArray
guard let gradient = CGGradient(
colorsSpace: CGColorSpaceCreateDeviceRGB(),
colors: colors,
locations: [0.0, 1.0]
) else { return }
ctx.saveGState()
ctx.addEllipse(in: rect)
ctx.clip()
ctx.drawLinearGradient(
gradient,
start: CGPoint(x: rect.midX, y: rect.minY),
end: CGPoint(x: rect.midX, y: rect.maxY),
options: []
)
ctx.restoreGState()
}
CGImage es una imagen rasterizada en Core Graphics que se puede cargar desde un archivo, crear programáticamente u obtener desde UIImage. CGImage contiene datos de píxeles, información del espacio de color, tamaño, profundidad de bits y disposición de datos. A diferencia de UIImage, CGImage no gestiona el escalado Retina — esta responsabilidad recae en el desarrollador a través del parámetro scale.
CGLayer es un búfer offline para prerasterización de contenido estático. Si el mismo conjunto de comandos de dibujo se ejecuta repetidamente (por ejemplo, un patrón de fondo), CGLayer lo rasteriza una vez y luego simplemente lo copia al contexto. Según Apple, el uso de CGLayer puede acelerar el dibujo repetitivo en 2–5 veces en CPU y hasta 10 veces con aceleración hardware.
Para cargar imágenes, use CGImageSource — una API potente para leer metadatos, miniaturas y fotogramas individuales de GIF/APNG. CGImageSource permite carga progresiva y recuperación solo de los fragmentos necesarios. Al trabajar con imágenes grandes (que exceden el tamaño de la pantalla), se recomienda crear un CGImageSource con almacenamiento en caché en disco y usar CGImageSourceCreateThumbnailAtIndex para mostrar una versión reducida.
func createLayer(ctx: CGContext, size: CGSize) -> CGLayer? {
guard let layer = CGLayer(ctx, size: size, auxiliaryInfo: nil) else { return nil }
let layerCtx = layer.context !
// dibujar una vez
layerCtx.setFillColor(UIColor.lightGray.cgColor)
layerCtx.addEllipse(in: CGRect(origin: .zero, size: size))
layerCtx.fillPath()
return layer
}
// uso en draw()
for i in 0..<20 {
ctx.draw(layer, at: CGPoint(x: CGFloat(i) * 30, y: 0))
}
Construyamos una Vista personalizada para mostrar una marca de agua en una imagen usando Core Graphics. La marca de agua incluye texto semitransparente y un logotipo vectorial superpuestos sobre la imagen original. El código demuestra el trabajo con CGContext, CGImage, texto y transparencia en un solo contexto.
class WatermarkView: UIView {
private let watermarkText = "IT Sectr"
private let watermarkOpacity: CGFloat = 0.3
override func draw(_ rect: CGRect) {
guard let ctx = UIGraphicsGetCurrentContext() else { return }
// dibujar imagen de fondo
UIImage(named: "background")?.draw(in: rect)
// configurar transparencia de marca de agua
ctx.saveGState()
ctx.translateBy(x: rect.midX, y: rect.midY)
ctx.rotate(by: -.pi / 6)
// texto semitransparente
let attributes: NSAttributedString.Attributes = [
.font: UIFont.boldSystemFont(ofSize: 48),
.foregroundColor: UIColor.white.withAlphaComponent(watermarkOpacity)
]
let textSize = watermarkText.size(withAttributes: attributes)
watermarkText.draw(
at: CGPoint(x: -textSize.width / 2, y: -textSize.height / 2),
withAttributes: attributes
)
// icono vectorial (círculo con cruz) debajo del texto
ctx.setStrokeColor(UIColor.white.withAlphaComponent(watermarkOpacity).cgColor)
ctx.setLineWidth(3)
ctx.addEllipse(in: CGRect(x: -25, y: -75, width: 50, height: 50))
ctx.strokePath()
ctx.moveTo(x: -15, y: -50)
ctx.addLineTo(x: 15, y: -50)
ctx.moveTo(x: 0, y: -65)
ctx.addLineTo(x: 0, y: -35)
ctx.strokePath()
ctx.restoreGState()
}
}
El código utiliza características clave de Core Graphics: saveGState/restoreGState para aislar los efectos de la marca de agua del fondo, translateBy y rotate para posicionamiento y rotación, texto semitransparente mediante withAlphaComponent y un icono vectorial a través de addEllipse y addLineTo. Toda la marca de agua se dibuja como una composición única después de la imagen de fondo.
Al crear marcas de agua para fotos en producción, es importante considerar el rendimiento. Si la imagen es más grande que la pantalla, redúzcala usando CGImageSourceCreateThumbnailAtIndex antes de aplicar la marca de agua. Core Graphics maneja todas las operaciones en la CPU — para procesamiento por lotes de docenas de imágenes, use una cola en segundo plano y CGBitmapContext para evitar bloquear la UI.
Preguntas frecuentes
UIKit es un framework UI de alto nivel que utiliza Core Graphics internamente para el dibujo. Core Graphics es una API C de bajo nivel para gráficos 2D. UIKit es más conveniente para elementos estándar, mientras que Core Graphics ofrece control total sobre cada píxel.
Core Graphics es adecuado para gráficos 2D estáticos, diagramas y elementos UI personalizados. Metal es para gráficos 3D, animaciones complejas y procesamiento de grandes arrays de píxeles con aceleración GPU. Para el 95% de las tareas UI, Core Graphics es suficiente.
Use CGImageSource para cargar miniaturas mediante createThumbnailAtIndex en lugar de la carga completa. Para mostrar imágenes grandes, cree CGImage con la opción de downsampling. Libere CGImage mediante CGImageRelease cuando ya no sea necesario.
Sí, Core Graphics incluye soporte completo de PDF mediante CGPDFDocument para lectura y CGPDFContext para crear documentos PDF. Puede dibujar cualquier contenido CGContext directamente en una página PDF conservando los vectores.
Core Graphics usa automáticamente la resolución del dispositivo al dibujar en pantalla. Para contextos offline, use UIGraphicsBeginImageContextWithOptions con scale = 0 (escala del sistema) o especifique explícitamente 2.0/3.0 para Retina/Retina HD.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también