CGContext iOS-ben — mi ez, módszerek és hogyan kezeljük a rajzolási kontextust

Szerző: IT Sectr Megjelenés: 2026-07-21 Olvasási idő: 9 perc

CGContext — a Core Graphics fő objektuma 2D rajzolási parancsok végrehajtásához iOS-ben és macOS-ben. Egy grafikus kontextust képvisel, amely tárolja az aktuális állapotot: kitöltő szín, vonalvastagság, transzformáció, vágóterület és betűtípusok. Minden rajzolási művelet — vonalak, téglalapok, szöveg, képek — a CGContext-en keresztül történik. A Apple Developer Documentation, 2026 szerint a CGContext az Apple ökoszisztémájában a teljes raszter és vektorgrafika alapja.

Főbb pontok

  • CGContext — a grafikus kontextus, amelyen keresztül az összes 2D Core Graphics parancs végrehajtódik.
  • setStrokeColor és setFillColor kezelik a vonalak és kitöltések színét a kontextusban.
  • addPath és drawPath lehetővé teszik tetszőleges CGPath kontúrok rajzolását.
  • clip(to:) beállítja a vágóterületet a rajzolás egy meghatározott zónára korlátozásához.
  • saveGState és restoreGState elmenti és visszaállítja a kontextus állapotainak vermét.

Mi az a CGContext?

CGContext — egy átlátszatlan típus (opaque type) a Core Graphics keretrendszerből, amely környezetet biztosít 2D megjelenítési parancsok végrehajtásához. Kezeli az állapotok vermét, az aktuális színteret, a koordináta-transzformációt és a vágóterületet. A CGContext az egyetlen objektum, amellyel az összes Quartz 2D rajzolófüggvény kommunikál — minden grafikai művelet rajta keresztül történik.

A CGContext több változatban létezik a céltól függően: bitmap context raszterképekkel való munkához memóriában, PDF context PDF dokumentumok generálásához, window context képernyőn való megjelenítéshez (amelyet a UIView biztosít a draw(_:) módszerben). iOS-ben a fejlesztők leggyakrabban a UIGraphicsGetCurrentContext()-ből a draw(_:) módszerben, vagy a UIGraphicsBeginImageContextWithOptions-ból offline megjelenítéshez kapott kontextussal dolgoznak.

A kontextus minden beállítást az állapotok vermén keresztül alkalmaz — a fejlesztő elmentheti az aktuális állapotot (saveGState), megváltoztathatja a paramétereket és visszaállíthatja az előző állapotot (restoreGState). Ez kritikus fontosságú összetett jelenetek megjelenítésekor, ahol a különböző elemek eltérő színeket, vonalvastagságokat és transzformációkat igényelnek. Az Apple WWDC 2023 szerint az állapotok vermének helyes használata javítja a kód olvashatóságát és megakadályozza a vizuális műtermékeket.

Állapotkezelés: saveGState és restoreGState

CGContextSaveGState a kontextus aktuális állapotának másolatát helyezi a verembe. Ez az állapot magában foglal minden beállítást: színek, vonalvastagság, transzformáció, árnyékok, vágóterület, betűtípusok. A paraméterek módosítása után a CGContextRestoreGState hívás visszaállítja a kontextust az elmentett állapotba, érvénytelenítve az összes köztes változtatást. A verem legfeljebb 32 állapotot tartalmazhat iOS-ben.

A verem gyakorlati alkalmazása

Különböző stílusú elemek csoportjának rajzolásakor (például egy diagram színes szektorai) az állapotok verme kiküszöböli az egyes paraméterek kézi megjegyzésének és visszaállításának szükségességét. saveGState/restoreGState nélkül a fejlesztőnek minden elem után újra be kellene állítania a színt, árnyékot és transzformációt. A verem használata lerövidíti a kódot és megszünteti a visszaállítási hibákat.

Fontos megtartani a mentések és visszaállítások egyensúlyát — minden saveGState-hez tartoznia kell egy restoreGState-nek. Az egyensúly megsértése állapotok szivárgásához vagy idő előtti visszaállításhoz vezet, ami kiszámíthatatlan megjelenítést okoz. Az Xcode statikus analizátora nem ellenőrzi a CGContext verem egyensúlyát, így a helyességért a fejlesztő a felelős. Javasolt a párok do/finally blokkokba csoportosítása.

swift
override func draw(_ rect: CGRect) {
    guard let ctx = UIGraphicsGetCurrentContext() else { return }

    ctx.saveGState()
    ctx.setStrokeColor(UIColor.red.cgColor)
    ctx.setLineWidth(3)
    ctx.addRect(CGRect(x: 50, y: 50, width: 200, height: 100))
    ctx.strokePath()
    ctx.restoreGState()
}

Színek és kitöltések

CGContextSetFillColorWithColor beállítja a kitöltő színt a következő műveletekhez. A szín CGColorRef-ként kerül átadásra, amely információt tartalmaz a színtérről és a színösszetevőkről. CGContextSetStrokeColorWithColor hasonlóan működik a körvonal színéhez. Az Apple a gyakran használt CGColorRef-ek gyorsítótárba helyezését ajánlja a teljesítmény javítása érdekében.

Gradiensek a CGContext-ben

CGContextDrawLinearGradient lineáris gradienst rajzol két pont között megadott színekkel. CGContextDrawRadialGradient radiális gradienst hoz létre, amely az egyik körből a másikba halad. A gradiensekkel való munkához először egy CGGradientRef objektumot kell létrehozni, amely színek és megállási pozíciók tömbjét tartalmazza. A CGContext-ben a gradiensek támogatják az RGB és Grayscale színtereket.

Egy terület kitöltése gradienstől megköveteli a vágóterület előzetes beállítását. Clip nélkül a gradiens a teljes kontextust kitölti, nem csak a kívánt alakzatot. A tipikus minta: út hozzáadása a kontextushoz, a clip meghívása a terület korlátozásához, majd a gradiens megrajzolása. Ezt a mintát minden olyan alkalmazásban használják, amely összetett alakzatok gradiens kitöltését igényli, a gomboktól a hátterekig.

FüggvényCélSzíntér
setFillColorKitöltő szín beállításaBármely (CGColor-on keresztül)
setStrokeColorKörvonal színének beállításaBármely (CGColor-on keresztül)
drawLinearGradientLineáris gradiens rajzolásaRGB vagy Grayscale
drawRadialGradientRadiális gradiens rajzolásaRGB vagy Grayscale

Kontúrok és vonalak rajzolása

CGContextAddPath hozzáad egy korábban létrehozott CGPathRef-et a kontextushoz későbbi megjelenítéshez. Az út hozzáadása után körvonalazható (strokePath), kitölthető (fillPath) vagy mindkét művelet elvégezhető. CGContextBeginPath új útot kezd, törölve az előzőt. A kontextus egyszerre csak egy aktív útot támogat.

Egyenes vonalak és görbék pontok alapján

CGContextMoveToPoint áthelyezi az út aktuális pontját a megadott koordinátákra. CGContextAddLineToPoint egyenes vonalat rajzol az aktuális ponttól a megadott pontig. CGContextAddCurveToPoint köbös Bézier-görbét ad hozzá, CGContextAddQuadCurveToPoint — kvadratikusat. CGContextClosePath egyenes vonallal zárja az útot az utolsó és az első pont között.

Ellentétben az UIBezierPath-szel, ahol ezeket a módszereket az út objektumán hívják meg, a CGContext-ben közvetlenül a kontextuson hívódnak. Ez a különbség fontos a megközelítés kiválasztásakor: az UIBezierPath kényelmesebb a kontúrok újrafelhasználásához, a CGContext — egyszeri megjelenítéshez minimális többletterheléssel. A CGContext támogatja továbbá a szaggatott vonalakat a CGContextSetLineDash-en, a rugalmas végeket a CGContextSetLineCap-en és a kapcsolódásokat a CGContextSetLineJoin-on keresztül.

swift
let ctx = UIGraphicsGetCurrentContext()!
ctx.beginPath()
ctx.moveTo(x: 50, y: 100)
ctx.addLineTo(x: 200, y: 100)
ctx.addCurveTo(x1: 250, y1: 50, x2: 300, y2: 150, x3: 350, y3: 100)
ctx.setStrokeColor(UIColor.blue.cgColor)
ctx.setLineWidth(5)
ctx.strokePath()

Vágóterület és transzformációk

CGContextClip a rajzolási területet az aktuális útra korlátozza. Az összes következő rajzolási művelet csak ezen a területen belül lesz látható. Ez az alapvető mechanizmus a maszkoláshoz, a sarkok lekerekítéséhez és egyedi elemhatárok létrehozásához. A vágóterület szintén mentésre és visszaállításra kerül a saveGState/restoreGState segítségével.

Koordináta-transzformáció

CGContextTranslateCTM eltolja a kontextus koordináta-rendszerének kezdőpontját. CGContextScaleCTM méretezi az X és Y tengelyeket. CGContextRotateCTM elforgatja a koordináta-rendszert az aktuális kezdőpont körül. A transzformációk összeadódnak — minden következő az aktuális koordináta-rendszerhez viszonyítva kerül alkalmazásra. Az összetett transzformációk (eltolás + forgatás + méretezés) animációhoz és elemek pozicionálásához használatosak.

A vágás és transzformálás együttes használata erőteljes lehetőségeket kínál: lehetőség van összetett maszk rajzolására vágással, majd transzformáció alkalmazására a teljes tartalomra. Tipikus példa — egy kép részének megjelenítése szögben lekerekített élekkel. A műveletek sorrendje fontos: először állítsa be a vágóterületet, majd alkalmazza a transzformációt, azután rajzolja meg a tartalmat. Az Apple azt ajánlja, hogy a CTM (Current Transformation Matrix) változtatásainak számát minimalizáljuk a megjelenítési ciklusban.

swift
override func draw(_ rect: CGRect) {
    guard let ctx = UIGraphicsGetCurrentContext() else { return }
    ctx.saveGState()

    // vágóterület — kör
    ctx.addEllipse(in: CGRect(x: 50, y: 50, width: 200, height: 200))
    ctx.clip()

    // tartalom transzformáció
    ctx.translateBy(x: 150, y: 150)
    ctx.rotate(by: .pi / 4)
    ctx.translateBy(x: -150, y: -150)

    UIImage(named: "photo")?.draw(at: CGPoint(x: 50, y: 50))
    ctx.restoreGState()
}

Rajzolási példa CGContext-ben

Nézzünk egy teljes példát egy gradiens diagram létrehozására CGContext használatával. A diagram három különböző színű szektort tartalmaz gradiens kitöltéssel és szöveges címkékkel. A kód a saveGState, clip, gradiensek és szövegmegjelenítés kombinációját mutatja be egy kontextusban.

swift
class PieChartView: UIView {

    private struct Slice {
        let color: UIColor
        let value: CGFloat
        let label: String
    }

    override func draw(_ rect: CGRect) {
        guard let ctx = UIGraphicsGetCurrentContext() else { return }

        let slices = [
            Slice(color: .systemRed, value: 0.4, label: "iOS"),
            Slice(color: .systemGreen, value: 0.35, label: "Android"),
            Slice(color: .systemBlue, value: 0.25, label: "Other")
        ]

        let center = CGPoint(x: bounds.midX, y: bounds.midY)
        let radius = bounds.width * 0.35
        var startAngle: CGFloat = -.pi / 2

        for slice in slices {
            let endAngle = startAngle + .pi * 2 * slice.value

            ctx.saveGState()
            ctx.moveTo(x: center.x, y: center.y)
            ctx.addArc(center: center, radius: radius,
                       startAngle: startAngle, endAngle: endAngle, clockwise: false)
            ctx.closePath()
            ctx.setFillColor(slice.color.cgColor)
            ctx.fillPath()

            // szöveges címke
            let midAngle = startAngle + endAngle / 2
            let labelPos = CGPoint(
                x: center.x + radius * 0.7 * cos(midAngle),
                y: center.y + radius * 0.7 * sin(midAngle)
            )
            slice.label.draw(at: labelPos, withAttributes: [
                .foregroundColor: UIColor.white,
                .font: UIFont.boldSystemFont(ofSize: 14)
            ])
            ctx.restoreGState()
            startAngle = endAngle
        }
    }
}

Ebben a példában a diagram minden szektora a saját saveGState/restoreGState blokkjában rajzolódik. Ez a megközelítés garantálja, hogy az egyik szektor szín- és útbeállításai nem befolyásolják a többit. Az addArc módszer ívet hoz létre a kezdő és végső szög között, a closePath a középponthoz zárja a szektort. A szöveges címke a szektor szögének középvonalára kerül, a pozíció számításához a cos és sin trigonometrikus függvények használatosak.

A gyakori úrajzolás teljesítményének javítása érdekében ajánlott a szögek és pozíciók számításainak gyorsítótárba helyezése egy külön tömbben. A CGContext az összes műveletet a CPU-n hajtja végre, így az összetett, tízesével szektort tartalmazó jelenetek optimalizálást igényelhetnek — például előzetes raszterizálást CGLayer-ben vagy a Metal használatát GPU-gyorsításhoz. A legtöbb 5–10 elemet tartalmazó UI feladat esetén a CGContext teljesítménye elfogadható.

Gyakran ismételt kérdések

Hogyan kapom meg az aktuális CGContext-et iOS-ben?

Hívja meg a UIGraphicsGetCurrentContext() függvényt a UIView draw(_:) metódusán belül vagy a UIGraphicsBeginImageContextWithOptions blokkon belül. CALayer rétegekhez használja a CALayerDelegate draw(in:) metódusát, amely egy kész kontextust kap.

Mi a különbség a fillPath és a strokePath között?

A fillPath kitölti az aktuális úton belüli területet a setFillColor színével. A strokePath vonalat rajzol az út mentén a setStrokeColor, setLineWidth és setLineCap paraméterekkel. Mindkét művelet egymás után történik: először fill, majd szükség esetén stroke.

Mi az a bitmap CGContext?

A Bitmap CGContext — egy CGBitmapContextCreate segítségével létrehozott kontextus, amely a képernyő helyett egy memóriabufferbe rajzol. Háttérkép-generáláshoz, grafikai feldolgozáshoz megjelenítés nélkül és textúrák létrehozásához Metal vagy OpenGL számára használatos.

Hogyan állíthatom vissza az összes CGContext beállítást?

A Core Graphics nem biztosít módszert az összes beállítás visszaállítására. Használja a saveGState függvényt a változtatások előtt és a restoreGState függvényt az eredeti állapotba való visszatéréshez. Alternatívaként létrehozhat egy új kontextust ugyanazokkal a paraméterekkel.

Miért nem jelenik meg a gradiens az alakzaton belül?

A drawLinearGradient meghívása előtt állítsa be a vágóterületet a clip segítségével a kívánt úton. Clip nélkül a gradiens a teljes kontextust kitölti. Sorrend: addPath → clip → drawLinearGradient — garantálja a gradienst az alakzaton belül.

Összefoglaló

  • CGContext — a Core Graphics központi objektuma az összes 2D rajzolási művelethez iOS-ben és macOS-ben.
  • saveGState és restoreGState kezelik a kontextus állapotainak vermét, megakadályozva a mellékhatásokat.
  • setFillColor és setStrokeColor beállítják a kitöltő és körvonal színét CGColorRef segítségével.
  • addPath, strokePath, fillPath tetszőleges CGPath kontúrokkal dolgoznak.
  • clip a rajzolási területet az aktuális útra korlátozza maszkokhoz és lekerekítésekhez.
  • translateCTM, scaleCTM, rotateCTM transzformálják a kontextus koordináta-rendszerét.
  • Minden CGContext művelet a CPU-n fut — összetett grafikához használjon CGLayer-t vagy Metal-t.

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is