Core Graphics — framework-ul de randare 2D de la Apple, parte a Core Foundation și disponibil pe iOS, macOS, tvOS și watchOS. Oferă o API C de nivel scăzut pentru lucrul cu grafica vectorială și raster, inclusiv desenarea contururilor, gradientelor, umbrelor, imaginilor și textului. Core Graphics stă la baza UIKit, SwiftUI și AppKit. Conform Apple Developer Documentation, 2026, framework-ul este folosit în peste 90% din aplicațiile iOS, deoarece orice element vizibil trece prin Core Graphics sau echivalentul său hardware.
Principalele
Core Graphics (cunoscut și ca Quartz 2D) este un framework care implementează motorul grafic 2D al Apple. Se bazează pe biblioteca grafică portabilă Quartz și utilizează un model de desenare pe bază de pagină (page-based), unde fiecare acțiune este o comandă într-o secvență care amintește de desenarea pe hârtie. Core Graphics suportă anti-aliasing, transparență (alpha compositing) și spații de culoare ICC.
Arhitectura Core Graphics este construită în jurul contextului grafic (CGContext), care încapsulează dispozitivul de ieșire țintă — ecran, imprimantă, document PDF sau buffer raster. Contextul gestionează setările curente: culoare, grosimea liniei, transformare, zona de decupare și fonturi. Această abordare asigură o API uniformă pentru diferite dispozitive de ieșire fără a modifica codul de desenare.
Core Graphics funcționează preponderent pe CPU, folosind un model vectorial (resolution-independent). Aceasta înseamnă că liniile și curbele sunt rasterizate la rezoluția curentă a dispozitivului în timpul randării. Spre deosebire de Metal, Core Graphics nu necesită gestionarea explicită a resurselor GPU — sistemul preia întreaga optimizare. Pentru majoritatea sarcinilor 2D (grafică, diagrame, elemente UI personalizate), performanța Core Graphics este suficientă pentru a menține 60 FPS.
Core Graphics include aproximativ 50 de tipuri de bază (opaque types), fiecare responsabil pentru o funcționalitate specifică. Toate tipurile respectă regulile de gestionare a memoriei Core Foundation: sunt create prin funcții cu Create în denumire, necesită apelul CGRelease și nu sunt compatibile ARC în Objective-C (însă Swift gestionează automat memoria prin adnotările CF_RETURNS_RETAINED).
CGContext — context de desenare, tipul central al framework-ului. CGPath — contur vectorial imutabil. CGColor — culoare cu specificarea spațiului de culoare. CGGradient — umplere gradient. CGImage — imagine raster. CGLayer — buffer offline optimizat pentru desenare repetitivă. CGDataProvider — sursă de date pentru imagini. CGColorSpace — spațiu de culoare (sRGB, Display P3, Gray).
Fiecare tip este proiectat pentru un overhead minim: CGPath poate fi stocat în cache și reutilizat între diferite contexte, CGColor este transformat în reprezentarea hardware GPU la transmitere, CGLayer stochează conținut rasterizat anterior. O astfel de arhitectură permite Core Graphics să funcționeze eficient atât în sarcini UI simple, cât și în editoare grafice profesionale.
| Tip | Destinație | Gestionare memorie |
|---|---|---|
| CGContext | Context grafic | CFRelease sau automat în Swift |
| CGPath | Contur vectorial | CFRelease (imutabil) |
| CGColor | Culoare în spațiul de culoare | CFRelease sau CGColorCreate |
| CGImage | Imagine raster | CFRelease (după creare) |
| CGLayer | Buffer offline | CFRelease sau CGLayerCreate |
CGPath — un obiect imutabil care descrie o secvență de segmente geometrice: linii drepte, curbe Bézier, arcuri și închideri. Spre deosebire de UIBezierPath, CGPath nu conține metode de desenare — stochează doar geometria. Pentru desenare, CGPath este adăugat în context (CGContextAddPath) și apoi desenat prin strokePath sau fillPath. Imutabilitatea garantează siguranța firelor de execuție și posibilitatea de stocare în cache.
CGPathCreateMutable creează o cale mutabilă (CGMutablePathRef) pentru construirea pas cu pas. După asamblarea finală, este transformată în CGPathRef imutabil. Apple recomandă minimizarea numărului de puncte în CGPath — contururile prea complexe (peste 1000 de segmente) încetinesc rasterizarea. Pentru optimizare, utilizați CGPathCreateCopyBySimplifyingPath, care elimină punctele coliniare redundante.
Pentru animația formei între două CGPath, puteți utiliza CABasicAnimation pe proprietatea path a CAShapeLayer. Limitare: ambele CGPath trebuie să aibă același număr de segmente (controls points). Funcția CGPathApply permite parcurgerea tuturor elementelor căii și compararea structurii lor. Dacă segmentele nu se potrivesc, animația va fi sacadată — în acest caz, utilizați CADisplayLink pentru interpolarea manuală a punctelor.
// creează cale mutabilă
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()
// convertește în imutabilă pentru stocare sigură în cache
let immutablePath: CGPath = mutablePath
CATransaction.perform {
shapeLayer.path = immutablePath
}
CGGradient — un obiect care definește o tranziție lină între două sau mai multe culori de-a lungul unei linii drepte (gradient liniar) sau de la centru spre margini (gradient radial). CGGradient se creează cu specificarea spațiului de culoare, a unui array de CGColorRef și a unui array de poziții de oprire de la 0.0 la 1.0. După creare, gradientul poate fi utilizat de mai multe ori în contexte diferite.
CGShading — un mecanism mai puternic care permite definirea unei funcții de schimbare a culorii de-a lungul căii. Spre deosebire de CGGradient, care lucrează cu un set fix de culori, CGShading folosește o funcție de callback (CGFunctionRef) care calculează culoarea în fiecare punct. Acest lucru permite crearea de gradiente complexe cu tranziții neliniare și scheme de culoare compuse.
Pentru desenarea unui gradient în interiorul unei figuri este necesară decuparea (clip) pe conturul acelei figuri. Ordinea: adăugați calea în context, apelați CGContextClip, apoi desenați gradientul. Fără decupare, gradientul umple întregul context. În iOS, se recomandă utilizarea CGGradient ca opțiune mai simplă și mai performantă — CGShading este justificat doar pentru funcții nestandard de schimbare a culorii.
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 — o imagine raster în Core Graphics, care poate fi încărcată dintr-un fișier, creată programatic sau obținută din UIImage. CGImage conține datele pixelilor, informații despre spațiul de culoare, dimensiune, adâncimea de biți și dispunerea datelor. Spre deosebire de UIImage, CGImage nu gestionează scalarea pentru Retina — această responsabilitate revine dezvoltatorului prin parametrul scale.
CGLayer — un buffer offline pentru rasterizarea prealabilă a conținutului static. Dacă același set de comenzi grafice este desenat în mod repetat (de exemplu, un model de fundal), CGLayer îl rasterizează o dată și apoi pur și simplu îl copiază în context. Conform datelor Apple, utilizarea CGLayer poate accelera desenarea repetitivă de 2–5 ori pe CPU și de până la 10 ori cu accelerare hardware.
Pentru încărcarea imaginilor, utilizați CGImageSource — o API puternică pentru citirea metadatelor, miniaturilor și cadrelor individuale din GIF/APNG. CGImageSource permite încărcarea progresivă a imaginii și obținerea doar a fragmentelor necesare. La lucrul cu imagini mari (care depășesc dimensiunea ecranului), se recomandă crearea CGImageSource cu opțiunea de cache pe disc și utilizarea CGImageSourceCreateThumbnailAtIndex pentru afișarea versiunii reduse.
func createLayer(ctx: CGContext, size: CGSize) -> CGLayer? {
guard let layer = CGLayer(ctx, size: size, auxiliaryInfo: nil) else { return nil }
let layerCtx = layer.context !
// desenează o dată
layerCtx.setFillColor(UIColor.lightGray.cgColor)
layerCtx.addEllipse(in: CGRect(origin: .zero, size: size))
layerCtx.fillPath()
return layer
}
// utilizare în draw()
for i in 0..<20 {
ctx.draw(layer, at: CGPoint(x: CGFloat(i) * 30, y: 0))
}
Vom dezvolta o View personalizată pentru afișarea unei filigrane pe o imagine folosind Core Graphics. Filigranul include text semi-transparent și un logo vectorial suprapuse peste imaginea originală. Codul demonstrează lucrul cu CGContext, CGImage, text și transparență într-un singur context.
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 }
// desenează imaginea de fundal
UIImage(named: "background")?.draw(in: rect)
// configurează transparența filigranului
ctx.saveGState()
ctx.translateBy(x: rect.midX, y: rect.midY)
ctx.rotate(by: -.pi / 6)
// text semi-transparent
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
)
// iconiță vectorială (cerc cu cruce) sub text
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()
}
}
În cod sunt utilizate capacitățile cheie ale Core Graphics: saveGState/restoreGState pentru izolarea efectelor filigranului de fundal, translateBy și rotate pentru poziționare și rotație, text semi-transparent prin withAlphaComponent și iconiță vectorială prin addEllipse și addLineTo. Întregul filigran este desenat ca o singură compoziție după imaginea de fundal.
La crearea filigranelor pentru fotografii în producție, este important să țineți cont de performanță. Dacă imaginea este mai mare decât ecranul, înainte de aplicarea filigranului, reduceți-o prin CGImageSourceCreateThumbnailAtIndex. Core Graphics procesează toate operațiile pe CPU — pentru procesarea în lot a zeci de imagini, utilizați o coadă de fundal și CGBitmapContext pentru a evita blocarea UI.
Întrebări frecvente
UIKit — un framework UI de nivel înalt care folosește Core Graphics intern pentru randare. Core Graphics — o API C de nivel scăzut pentru grafică 2D. UIKit este mai convenabil pentru elementele standard, Core Graphics oferă control total asupra fiecărui pixel.
Core Graphics este potrivit pentru grafică 2D statică, diagrame și elemente UI personalizate. Metal — pentru grafică 3D, animații complexe și procesarea unor mari volume de pixeli cu accelerare GPU. Pentru 95% din sarcinile UI, Core Graphics este suficient.
Utilizați CGImageSource pentru încărcarea miniaturilor prin createThumbnailAtIndex în loc de încărcarea completă. Pentru afișarea imaginilor mari, creați CGImage cu opțiunea downsample. Eliberați CGImage prin CGImageRelease când nu mai este necesar.
Da, Core Graphics include suport complet PDF prin CGPDFDocument pentru citire și CGPDFContext pentru crearea documentelor PDF. Puteți desena orice conținut CGContext direct pe o pagină PDF cu păstrarea vectorilor.
Core Graphics utilizează automat rezoluția dispozitivului la randarea pe ecran. Pentru contextele offline, utilizați UIGraphicsBeginImageContextWithOptions cu parametrul scale = 0 (scara sistemului) sau specificați explicit 2.0/3.0 pentru Retina/Retina HD.
Concluzii
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și