CGContext di iOS — apa itu, metode dan cara mengelola konteks menggambar

Penulis: IT Sectr Diterbitkan: 2026-07-21 Waktu membaca: 9 mnt

CGContext — objek utama Core Graphics untuk mengeksekusi perintah menggambar 2D di iOS dan macOS. Ini mewakili konteks grafis yang menyimpan status saat ini: warna isian, ketebalan garis, transformasi, area kliping, dan font. Semua operasi menggambar — garis, persegi panjang, teks, gambar — dilakukan melalui CGContext. Menurut Apple Developer Documentation, 2026, CGContext adalah fondasi dari seluruh grafis raster dan vektor di ekosistem Apple.

Poin Penting

  • CGContext — konteks grafis tempat semua perintah 2D Core Graphics dijalankan.
  • setStrokeColor dan setFillColor mengelola warna garis dan isian dalam konteks.
  • addPath dan drawPath memungkinkan menggambar kontur CGPath sembarang.
  • clip(to:) menetapkan area kliping untuk membatasi gambar ke zona tertentu.
  • saveGState dan restoreGState menyimpan dan mengembalikan tumpukan status konteks.

Apa itu CGContext?

CGContext — tipe buram (opaque type) dari framework Core Graphics yang mewakili lingkungan untuk mengeksekusi perintah rendering 2D. Ini mengelola tumpukan status, ruang warna saat ini, transformasi koordinat, dan area kliping. CGContext adalah satu-satunya objek yang berinteraksi dengan semua fungsi menggambar Quartz 2D — setiap operasi grafis melewatinya.

CGContext ada dalam beberapa varian tergantung pada tujuannya: bitmap context untuk bekerja dengan gambar raster di memori, PDF context untuk menghasilkan dokumen PDF, window context untuk rendering di layar (disediakan oleh UIView di draw(_:)). Di iOS, pengembang paling sering bekerja dengan konteks yang diperoleh dari UIGraphicsGetCurrentContext() di dalam metode draw(_:) atau dari UIGraphicsBeginImageContextWithOptions untuk rendering offline.

Konteks menerapkan semua pengaturan melalui tumpukan status — pengembang dapat menyimpan status saat ini (saveGState), mengubah parameter, dan mengembalikan status sebelumnya (restoreGState). Ini sangat penting saat merender adegan kompleks di mana elemen yang berbeda membutuhkan warna, ketebalan garis, dan transformasi yang berbeda. Menurut Apple WWDC 2023, penggunaan tumpukan status yang benar meningkatkan keterbacaan kode dan mencegah artefak visual.

Manajemen Status: saveGState dan restoreGState

CGContextSaveGState menempatkan salinan status konteks saat ini ke dalam tumpukan. Status ini mencakup semua pengaturan: warna, ketebalan garis, transformasi, bayangan, area kliping, font. Setelah mengubah parameter, panggilan CGContextRestoreGState mengembalikan konteks ke status yang disimpan, membatalkan semua perubahan sementara. Tumpukan dapat menampung hingga 32 status di iOS.

Aplikasi Praktis Tumpukan

Saat menggambar sekelompok elemen dengan gaya berbeda (misalnya, sektor diagram berwarna-warni), tumpukan status menghilangkan kebutuhan untuk mengingat dan mengembalikan setiap parameter secara manual. Tanpa saveGState/restoreGState, pengembang harus mengatur ulang warna, bayangan, dan transformasi setelah setiap elemen. Penggunaan tumpukan memperpendek kode dan menghilangkan kesalahan pengembalian.

Penting untuk menjaga keseimbangan penyimpanan dan pengembalian — setiap saveGState harus memiliki restoreGState yang sesuai. Pelanggaran keseimbangan menyebabkan kebocoran status atau pengembalian prematur, yang mengakibatkan tampilan tidak terduga. Penganalisis statis Xcode tidak memeriksa keseimbangan tumpukan CGContext, sehingga tanggung jawab atas kebenaran ada pada pengembang. Disarankan untuk mengelompokkan pasangan dalam blok do/finally.

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

Warna dan Isian

CGContextSetFillColorWithColor menetapkan warna isian untuk operasi selanjutnya. Warna dikirim sebagai CGColorRef, yang berisi informasi tentang ruang warna dan komponen warna. CGContextSetStrokeColorWithColor bekerja serupa untuk warna goresan. Apple merekomendasikan caching CGColorRef yang sering digunakan untuk meningkatkan kinerja.

Gradien di CGContext

CGContextDrawLinearGradient menggambar gradien linier antara dua titik dengan warna yang ditentukan. CGContextDrawRadialGradient membuat gradien radial yang bertransisi dari satu lingkaran ke lingkaran lainnya. Untuk bekerja dengan gradien, pertama-tama dibuat objek CGGradientRef yang berisi larik warna dan posisi berhenti. Gradien di CGContext mendukung ruang warna RGB dan Grayscale.

Mengisi area dengan gradien memerlukan pengaturan awal area kliping. Tanpa clip, gradien akan mengisi seluruh konteks, bukan hanya bentuk yang diinginkan. Pola tipikal: tambahkan jalur ke konteks, panggil clip untuk membatasi area, lalu gambar gradien. Pola ini digunakan di semua aplikasi yang memerlukan pengisian gradien bentuk kompleks, dari tombol hingga latar belakang.

FungsiTujuanRuang Warna
setFillColorMenetapkan warna isianSemua (melalui CGColor)
setStrokeColorMenetapkan warna goresanSemua (melalui CGColor)
drawLinearGradientMenggambar gradien linierRGB atau Grayscale
drawRadialGradientMenggambar gradien radialRGB atau Grayscale

Menggambar Kontur dan Garis

CGContextAddPath menambahkan CGPathRef yang telah dibuat sebelumnya ke konteks untuk rendering selanjutnya. Setelah jalur ditambahkan, dapat digores (strokePath), diisi (fillPath), atau keduanya. CGContextBeginPath memulai jalur baru, membersihkan yang sebelumnya. Konteks hanya mendukung satu jalur aktif pada satu waktu.

Garis Lurus dan Kurva Berdasarkan Titik

CGContextMoveToPoint memindahkan titik jalur saat ini ke koordinat yang ditentukan. CGContextAddLineToPoint menggambar garis lurus dari titik saat ini ke titik yang diberikan. CGContextAddCurveToPoint menambahkan kurva Bézier kubik, CGContextAddQuadCurveToPoint — kuadratik. CGContextClosePath menutup jalur dengan garis lurus antara titik terakhir dan pertama.

Tidak seperti UIBezierPath, di mana semua metode ini dipanggil pada objek jalur, di CGContext metode ini dipanggil langsung pada konteks. Perbedaan ini penting saat memilih pendekatan: UIBezierPath lebih nyaman untuk penggunaan kembali kontur, CGContext — untuk rendering satu kali dengan overhead minimal. CGContext juga mendukung garis putus-putus melalui CGContextSetLineDash, ujung fleksibel melalui CGContextSetLineCap, dan sambungan melalui 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()

Area Kliping dan Transformasi

CGContextClip membatasi area menggambar ke jalur saat ini. Semua operasi menggambar berikutnya hanya akan terlihat di dalam area ini. Ini adalah mekanisme dasar untuk masking, pembulatan sudut, dan pembuatan batas elemen kustom. Area kliping juga disimpan dan dipulihkan melalui saveGState/restoreGState.

Transformasi Koordinat

CGContextTranslateCTM menggeser titik asal koordinat konteks. CGContextScaleCTM menskala sumbu X dan Y. CGContextRotateCTM memutar sistem koordinat di sekitar titik asal saat ini. Transformasi bersifat kumulatif — setiap transformasi berikutnya diterapkan relatif terhadap sistem koordinat saat ini. Transformasi gabungan (pergeseran + rotasi + skala) digunakan untuk animasi dan penentuan posisi elemen.

Penggunaan gabungan kliping dan transformasi memberikan kemampuan yang kuat: seseorang dapat menggambar masker kompleks melalui kliping, lalu menerapkan transformasi ke seluruh konten. Contoh tipikal — menampilkan bagian gambar pada sudut dengan tepi membulat. Urutan operasi penting: pertama atur area kliping, lalu terapkan transformasi, lalu gambar konten. Apple merekomendasikan untuk meminimalkan jumlah perubahan CTM (Current Transformation Matrix) dalam loop rendering.

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

    // area kliping — lingkaran
    ctx.addEllipse(in: CGRect(x: 50, y: 50, width: 200, height: 200))
    ctx.clip()

    // transformasi konten
    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()
}

Contoh Menggambar di CGContext

Mari kita lihat contoh lengkap pembuatan diagram gradien menggunakan CGContext. Diagram mencakup tiga sektor berwarna berbeda dengan isian gradien dan label teks. Kode ini menunjukkan kombinasi saveGState, clip, gradien, dan rendering teks dalam satu konteks.

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

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

Dalam contoh ini, setiap sektor diagram digambar dalam blok saveGState/restoreGState-nya sendiri. Pendekatan ini memastikan bahwa pengaturan warna dan jalur untuk satu sektor tidak mempengaruhi yang lain. Metode addArc membuat busur dari sudut awal hingga akhir, closePath menutup sektor ke pusat. Label teks ditempatkan pada garis tengah sudut sektor menggunakan fungsi trigonometri cos dan sin untuk perhitungan posisi.

Untuk meningkatkan kinerja saat sering menggambar ulang, disarankan untuk menyimpan cache perhitungan sudut dan posisi dalam larik terpisah. CGContext menjalankan semua operasi di CPU, sehingga adegan kompleks dengan puluhan sektor mungkin memerlukan pengoptimalan — misalnya, rasterisasi awal di CGLayer atau penggunaan Metal untuk akselerasi GPU. Untuk sebagian besar tugas UI dengan 5–10 elemen, kinerja CGContext masih dapat diterima.

Pertanyaan yang Sering Diajukan

Bagaimana cara mendapatkan CGContext saat ini di iOS?

Panggil UIGraphicsGetCurrentContext() di dalam metode draw(_:) UIView atau di dalam blok UIGraphicsBeginImageContextWithOptions. Untuk lapisan CALayer, gunakan draw(in:) delegasi CALayerDelegate yang menerima konteks siap pakai.

Apa perbedaan antara fillPath dan strokePath?

fillPath mengisi area dalam jalur saat ini dengan warna dari setFillColor. strokePath menggambar garis di sepanjang jalur dengan parameter setStrokeColor, setLineWidth, dan setLineCap. Kedua operasi dilakukan secara berurutan: pertama fill, lalu stroke jika diperlukan.

Apa itu bitmap CGContext?

Bitmap CGContext — konteks yang dibuat melalui CGBitmapContextCreate yang menggambar ke buffer memori, bukan ke layar. Digunakan untuk pembuatan gambar latar belakang, pemrosesan grafis tanpa ditampilkan, dan pembuatan tekstur untuk Metal atau OpenGL.

Bagaimana cara mereset semua pengaturan CGContext?

Core Graphics tidak menyediakan metode untuk mereset semua pengaturan. Gunakan saveGState sebelum perubahan dan restoreGState untuk kembali ke status awal. Sebagai alternatif, Anda dapat membuat konteks baru dengan parameter yang sama.

Mengapa gradien tidak muncul di dalam bentuk?

Sebelum memanggil drawLinearGradient, atur area kliping melalui clip pada jalur yang diinginkan. Tanpa clip, gradien mengisi seluruh konteks. Urutan: addPath → clip → drawLinearGradient — menjamin gradien di dalam bentuk.

Kesimpulan

  • CGContext — objek pusat Core Graphics untuk semua operasi menggambar 2D di iOS dan macOS.
  • saveGState dan restoreGState mengelola tumpukan status konteks, mencegah efek samping.
  • setFillColor dan setStrokeColor menetapkan warna isian dan goresan melalui CGColorRef.
  • addPath, strokePath, fillPath bekerja dengan kontur CGPath sembarang.
  • clip membatasi area menggambar ke jalur saat ini untuk masker dan pembulatan.
  • translateCTM, scaleCTM, rotateCTM mentransformasi sistem koordinat konteks.
  • Semua operasi CGContext dijalankan di CPU — untuk grafis kompleks, gunakan CGLayer atau Metal.

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga