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 — 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.
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.
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.
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()
}
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.
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.
| Fungsi | Tujuan | Ruang Warna |
|---|---|---|
| setFillColor | Menetapkan warna isian | Semua (melalui CGColor) |
| setStrokeColor | Menetapkan warna goresan | Semua (melalui CGColor) |
| drawLinearGradient | Menggambar gradien linier | RGB atau Grayscale |
| drawRadialGradient | Menggambar gradien radial | RGB atau Grayscale |
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.
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.
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()
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.
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.
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()
}
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.
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
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.
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.
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.
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.
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
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.
Baca juga