CGContext in iOS — was es ist, Methoden und wie man den Zeichnungskontext verwaltet

Autor: IT Sectr Veröffentlicht: 2026-07-21 Lesezeit: 9 Min.

CGContext ist das primäre Core Graphics-Objekt zur Ausführung von 2D-Zeichenbefehlen in iOS und macOS. Es repräsentiert einen Grafik-Kontext, der den aktuellen Zustand speichert: Füllfarbe, Linienstärke, Transformation, Beschneidungsbereich und Schriftarten. Alle Zeichenoperationen — Linien, Rechtecke, Text, Bilder — werden über CGContext ausgeführt. Laut Apple Developer Documentation, 2026 ist CGContext die Grundlage aller Raster- und Vektorgrafiken im Apple-Ökosystem.

Wichtige Punkte

  • CGContext ist der Grafik-Kontext, über den alle 2D-Core Graphics-Befehle ausgeführt werden.
  • setStrokeColor und setFillColor verwalten die Farbe von Linien und Füllungen im Kontext.
  • addPath und drawPath ermöglichen das Zeichnen beliebiger CGPath-Konturen.
  • clip(to:) legt den Beschneidungsbereich fest, um das Zeichnen auf eine bestimmte Zone zu beschränken.
  • saveGState und restoreGState speichern und stellen den Zustandsstapel des Kontexts wieder her.

Was ist CGContext?

CGContext ist ein undurchsichtiger Typ (opaque type) aus dem Core Graphics-Framework, der eine Umgebung zur Ausführung von 2D-Rendering-Befehlen darstellt. Er verwaltet den Zustandsstapel, den aktuellen Farbraum, die Koordinatentransformation und den Beschneidungsbereich. CGContext ist das einzige Objekt, mit dem alle Quartz 2D-Zeichenfunktionen interagieren — jede Grafikoperation läuft durch ihn.

CGContext existiert in mehreren Varianten, je nach Zweck: Bitmap-Kontext für die Arbeit mit Rasterbildern im Speicher, PDF-Kontext zur Erstellung von PDF-Dokumenten, Fenster-Kontext für die Bildschirmdarstellung (bereitgestellt von UIView in draw(_:)). iOS-Entwickler arbeiten am häufigsten mit einem Kontext, der von UIGraphicsGetCurrentContext() innerhalb der draw(_:)-Methode oder von UIGraphicsBeginImageContextWithOptions für das Offline-Rendering bezogen wird.

Der Kontext wendet alle Einstellungen über einen Zustandsstapel an — der Entwickler kann den aktuellen Zustand speichern (saveGState), Parameter ändern und den vorherigen Zustand wiederherstellen (restoreGState). Dies ist bei komplexen Szenen, in denen verschiedene Elemente unterschiedliche Farben, Linienstärken und Transformationen erfordern, von entscheidender Bedeutung. Laut Apple WWDC 2023 verbessert die richtige Verwendung des Zustandsstapels die Lesbarkeit des Codes und verhindert visuelle Artefakte.

Zustandsverwaltung: saveGState und restoreGState

CGContextSaveGState legt eine Kopie des aktuellen Kontextzustands auf den Stapel. Dieser Zustand umfasst alle Einstellungen: Farben, Linienstärke, Transformation, Schatten, Beschneidungsbereich, Schriftarten. Nach der Änderung von Parametern bringt der Aufruf von CGContextRestoreGState den Kontext in den gespeicherten Zustand zurück und macht alle zwischenzeitlichen Änderungen rückgängig. Der Stapel kann unter iOS bis zu 32 Zustände aufnehmen.

Praktische Anwendung des Stapels

Beim Zeichnen von Elementgruppen mit unterschiedlichen Stilen (z.B. mehrfarbige Diagrammsektoren) macht der Zustandsstapel das manuelle Merken und Wiederherstellen jedes Parameters überflüssig. Ohne saveGState/restoreGState müsste der Entwickler nach jedem Element Farbe, Schatten und Transformation zurücksetzen. Die Verwendung des Stapels reduziert den Code und verhindert Wiederherstellungsfehler.

Es ist wichtig, ein Gleichgewicht zwischen Speichern und Wiederherstellen zu wahren — jeder saveGState muss einen passenden restoreGState haben. Ein Ungleichgewicht führt zu Zustandslecks oder vorzeitiger Wiederherstellung, was unvorhersehbare Darstellung verursacht. Der statische Analysator von Xcode prüft das Stapelgleichgewicht von CGContext nicht, daher liegt die Korrektheit in der Verantwortung des Entwicklers. Es wird empfohlen, Paare in do/finally-Blöcken zu gruppieren.

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()
}

Farben und Füllungen

CGContextSetFillColorWithColor legt die Füllfarbe für nachfolgende Operationen fest. Die Farbe wird als CGColorRef übergeben, die Informationen über den Farbraum und die Farbkomponenten enthält. CGContextSetStrokeColorWithColor funktioniert analog für die Strichfarbe. Apple empfiehlt, häufig verwendete CGColorRef-Werte zur Leistungssteigerung zwischenzuspeichern.

Farbverläufe in CGContext

CGContextDrawLinearGradient zeichnet einen linearen Farbverlauf zwischen zwei Punkten mit angegebenen Farben. CGContextDrawRadialGradient erstellt einen radialen Farbverlauf, der von einem Kreis zum anderen übergeht. Für die Arbeit mit Farbverläufen wird zunächst ein CGGradientRef-Objekt erstellt, das ein Array von Farben und Stoppositionen enthält. Farbverläufe in CGContext unterstützen sowohl RGB- als auch Graustufen-Farbräume.

Das Füllen eines Bereichs mit einem Farbverlauf erfordert das vorherige Festlegen eines Beschneidungsbereichs. Ohne clip füllt der Farbverlauf den gesamten Kontext, nicht nur die gewünschte Form. Das typische Muster: Pfad zum Kontext hinzufügen, clip aufrufen, um den Bereich einzuschränken, dann den Farbverlauf zeichnen. Dieses Muster wird in allen Anwendungen verwendet, die Farbverlaufsfüllungen komplexer Formen benötigen, von Schaltflächen bis zu Hintergründen.

FunktionZweckFarbraum
setFillColorLegt die Füllfarbe festJeder (über CGColor)
setStrokeColorLegt die Strichfarbe festJeder (über CGColor)
drawLinearGradientZeichnet einen linearen FarbverlaufRGB oder Graustufen
drawRadialGradientZeichnet einen radialen FarbverlaufRGB oder Graustufen

Zeichnen von Pfaden und Linien

CGContextAddPath fügt einen zuvor erstellten CGPathRef zum Kontext für die anschließende Darstellung hinzu. Nach dem Hinzufügen eines Pfads kann dieser konturiert (strokePath), gefüllt (fillPath) oder beides werden. CGContextBeginPath startet einen neuen Pfad und löscht den vorherigen. Der Kontext unterstützt jeweils nur einen aktiven Pfad.

Gerade Linien und Kurven nach Punkten

CGContextMoveToPoint bewegt den aktuellen Konturpunkt zu den angegebenen Koordinaten. CGContextAddLineToPoint zeichnet eine gerade Linie vom aktuellen Punkt zum angegebenen Punkt. CGContextAddCurveToPoint fügt eine kubische Bézierkurve hinzu, CGContextAddQuadCurveToPoint eine quadratische. CGContextClosePath schließt die Kontur mit einer geraden Linie zwischen dem letzten und ersten Punkt.

Im Gegensatz zu UIBezierPath, bei dem alle diese Methoden auf dem Pfadobjekt aufgerufen werden, werden sie in CGContext direkt auf dem Kontext aufgerufen. Dieser Unterschied ist bei der Wahl des Ansatzes wichtig: UIBezierPath ist für die Wiederverwendung von Pfaden praktischer, CGContext eignet sich besser für einmaliges Zeichnen mit minimalem Overhead. CGContext unterstützt auch gestrichelte Linien über CGContextSetLineDash, flexible Enden über CGContextSetLineCap und Verbindungen über CGContextSetLineJoin.

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()

Beschneidungsbereich und Transformationen

CGContextClip schränkt den Zeichenbereich auf den aktuellen Pfad ein. Alle nachfolgenden Zeichenoperationen sind nur innerhalb dieses Bereichs sichtbar. Dies ist der grundlegende Mechanismus zum Maskieren, Abrunden von Ecken und Erstellen benutzerdefinierter Elementgrenzen. Der Beschneidungsbereich wird auch über saveGState/restoreGState gespeichert und wiederhergestellt.

Koordinatentransformationen

CGContextTranslateCTM verschiebt den Ursprung des Koordinatensystems des Kontexts. CGContextScaleCTM skaliert die X- und Y-Achsen. CGContextRotateCTM dreht das Koordinatensystem um den aktuellen Ursprung. Transformationen akkumulieren — jede nachfolgende wird relativ zum aktuellen Koordinatensystem angewendet. Zusammengesetzte Transformationen (Verschiebung + Drehung + Skalierung) werden für Animation und Elementpositionierung verwendet.

Die Kombination von Beschneidung und Transformation bietet leistungsstarke Möglichkeiten: Eine komplexe Maske kann durch Beschneidung gezeichnet werden, dann kann eine Transformation auf den gesamten Inhalt angewendet werden. Ein typisches Beispiel ist die Darstellung eines Bildteils in einem Winkel mit abgerundeten Ecken. Die Reihenfolge der Operationen ist wichtig: Zuerst den Beschneidungsbereich festlegen, dann die Transformation anwenden, dann den Inhalt zeichnen. Apple empfiehlt, Änderungen der CTM (Current Transformation Matrix) im Zeichen-Loop zu minimieren.

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

    // clipping region - circle
    ctx.addEllipse(in: CGRect(x: 50, y: 50, width: 200, height: 200))
    ctx.clip()

    // content transformation
    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()
}

Zeichenbeispiel in CGContext

Betrachten wir ein vollständiges Beispiel zur Erstellung eines Farbverlaufsdiagramms mit CGContext. Das Diagramm umfasst drei Sektoren in verschiedenen Farben mit Farbverlaufsfüllungen und Textbeschriftungen. Der Code demonstriert die Kombination von saveGState, clip, Farbverläufen und Textdarstellung in einem einzigen Kontext.

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()

            // text label
            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
        }
    }
}

In diesem Beispiel wird jeder Diagrammsektor in einem eigenen saveGState/restoreGState-Block gezeichnet. Dieser Ansatz stellt sicher, dass die Farb- und Pfadeinstellungen eines Sektors andere nicht beeinflussen. Die addArc-Methode erzeugt einen Bogen vom Start- zum Endwinkel, und closePath schließt den Sektor zur Mitte hin. Der Beschriftungstext wird am mittleren Winkel des Sektors platziert, wobei die trigonometrischen Funktionen cos und sin zur Positionsberechnung verwendet werden.

Zur Leistungsverbesserung bei häufigen Neuzeichnungen wird empfohlen, Winkel- und Positionsberechnungen in einem separaten Array zwischenzuspeichern. CGContext führt alle Operationen auf der CPU aus, daher können komplexe Szenen mit Dutzenden von Sektoren Optimierung erfordern — zum Beispiel Vorab-Rendering in CGLayer oder die Verwendung von Metal für GPU-Beschleunigung. Für die meisten UI-Aufgaben mit 5–10 Elementen bleibt die Leistung von CGContext akzeptabel.

Häufig gestellte Fragen

Wie erhalte ich den aktuellen CGContext in iOS?

Rufen Sie UIGraphicsGetCurrentContext() innerhalb der draw(_:)-Methode von UIView oder innerhalb eines UIGraphicsBeginImageContextWithOptions-Blocks auf. Für CALayer-Ebenen verwenden Sie die draw(in:)-Methode von CALayerDelegate, die einen fertigen Kontext empfängt.

Was ist der Unterschied zwischen fillPath und strokePath?

fillPath füllt das Innere des aktuellen Pfads mit der Farbe von setFillColor. strokePath zeichnet eine Linie entlang des Pfads mit den Parametern von setStrokeColor, setLineWidth und setLineCap. Beide Operationen werden nacheinander ausgeführt: zuerst Füllung, dann bei Bedarf Strich.

Was ist ein Bitmap-CGContext?

Bitmap CGContext ist ein über CGBitmapContextCreate erstellter Kontext, der in einen Speicherpuffer statt auf den Bildschirm zeichnet. Er wird für die Hintergrundbilderzeugung, Grafikverarbeitung ohne Anzeige und die Erstellung von Texturen für Metal oder OpenGL verwendet.

Wie setze ich alle CGContext-Einstellungen zurück?

Core Graphics bietet keine Methode zum Zurücksetzen aller Einstellungen. Verwenden Sie saveGState vor Änderungen und restoreGState zur Rückkehr zum ursprünglichen Zustand. Alternativ können Sie einen neuen Kontext mit denselben Parametern erstellen.

Warum wird der Farbverlauf nicht innerhalb der Form angezeigt?

Vor dem Aufruf von drawLinearGradient legen Sie den Beschneidungsbereich über clip auf dem gewünschten Pfad fest. Ohne clip füllt der Farbverlauf den gesamten Kontext. Reihenfolge: addPath → clip → drawLinearGradient — garantiert den Farbverlauf innerhalb der Form.

Zusammenfassung

  • CGContext ist das zentrale Core Graphics-Objekt für alle 2D-Zeichenoperationen auf iOS und macOS.
  • saveGState und restoreGState verwalten den Zustandsstapel des Kontexts und verhindern Seiteneffekte.
  • setFillColor und setStrokeColor legen Füll- und Strichfarben über CGColorRef fest.
  • addPath, strokePath, fillPath arbeiten mit beliebigen CGPath-Konturen.
  • clip schränkt den Zeichenbereich für Masken und Rundungen auf den aktuellen Pfad ein.
  • translateCTM, scaleCTM, rotateCTM transformieren das Koordinatensystem des Kontexts.
  • Alle CGContext-Operationen laufen auf der CPU — für komplexe Grafiken verwenden Sie CGLayer oder Metal.

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch