draw(_:) / drawRect — adalah metode kelas UIView (di Swift) dan analognya di Objective-C (drawRect:), yang bertanggung jawab untuk merender konten view menggunakan Core Graphics. Sistem memanggil metode ini secara otomatis saat pertama kali view muncul di layar dan setelah pemanggilan setNeedsDisplay(). Menurut Apple Documentation (2025), draw(_:) adalah satu-satunya metode di mana pengembang memiliki akses ke konteks grafis layar saat ini untuk menggambar kustom. Melakukan override draw(_:) memberikan kendali penuh atas tampilan komponen — dari bentuk geometris sederhana hingga grafis animasi yang kompleks.
Poin Utama
draw(_:) — adalah metode instance UIView yang dipanggil UIKit untuk merender konten view. Di dalam metode ini, pengembang mendapatkan akses ke konteks grafis CGContext dan menggunakan API Core Graphics untuk menggambar garis, isian, teks, dan gambar. drawRect: di Objective-C melakukan fungsi yang sama, tetapi dengan sintaks yang berbeda: satu-satunya parameter adalah CGRect yang menentukan area yang akan digambar ulang.
Menurut Apple Engineering (2024), draw(_:) bekerja melalui CPU-rendering Bitmap Graphics Context, yang memberikan fleksibilitas maksimal, tetapi membutuhkan lebih banyak sumber daya dibandingkan CALayer. Keputusan untuk menggunakan draw(_:) diambil berdasarkan kompleksitas grafis dan persyaratan kinerja.
Di Swift, metode dideklarasikan sebagai override func draw(_ rect: CGRect), di mana rect adalah persegi panjang yang perlu digambar ulang. Di Objective-C signature-nya adalah - (void)drawRect:(CGRect)rect. Parameter rect bisa lebih kecil dari bounds view saat penggambaran ulang parsial melalui setNeedsDisplay(_:).
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextFillRect(context, rect);
}
Sistem secara otomatis memanggil draw(_:) dalam skenario yang ditentukan secara ketat. Memahami pemicu ini membantu menghindari penggambaran ulang yang tidak perlu dan mengoptimalkan kinerja view. Di bawah ini tercantum semua kasus pemanggilan otomatis metode.
Dokumentasi Apple memperingatkan: jangan pernah memanggil draw(_:) secara langsung. Sistem sendiri yang memutuskan kapan akan melakukan penggambaran, dan pemanggilan langsung merusak mekanisme caching internal. Untuk meminta penggambaran ulang, selalu gunakan setNeedsDisplay() atau setNeedsDisplay(_:).
Melakukan override draw(_:) di Swift dimulai dengan mendapatkan konteks grafis dan pemanggilan Core Graphics selanjutnya. Disarankan untuk membuat metode terpisah untuk blok logika penggambaran — ini meningkatkan keterbacaan dan kemudahan pengujian kode.
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let context = UIGraphicsGetCurrentContext() else { return }
// Parameter garis
context.setStrokeColor(UIColor.darkGray.cgColor)
context.setLineWidth(2.0)
// Menggambar segitiga
context.move(to: CGPoint(x: rect.midX, y: rect.minY + 10))
context.addLine(to: CGPoint(x: rect.maxX - 10, y: rect.maxY - 10))
context.addLine(to: CGPoint(x: rect.minX + 10, y: rect.maxY - 10))
context.closePath()
context.strokePath()
}
Dalam contoh ini draw(_:) menggambar segitiga dengan garis tepi abu-abu gelap setebal 2 piksel. Pemanggilan super.draw(rect) di awal metode direkomendasikan oleh Apple untuk mempertahankan logika penggambaran induk, meskipun implementasi default draw(_:) di UIView kosong.
Setiap pemanggilan draw(_:) harus memberikan hasil yang identik dengan data masukan yang sama. Ini memungkinkan sistem menyimpan cache hasil dan tidak memanggil draw(_:) lagi jika konten view tidak berubah. Jangan gunakan nilai acak, waktu sistem, atau permintaan jaringan di dalam draw(_:).
drawRect: — secara historis merupakan versi pertama metode, muncul di iOS 2.0 bersama Objective-C. Di Swift metode ini diubah namanya menjadi draw(_:) dengan menggunakan parameter eksternal _. Secara fungsional metode ini identik: keduanya menerima CGRect dari area yang akan digambar ulang dan menggunakan UIGraphicsGetCurrentContext() untuk mengakses konteks grafis.
| Karakteristik | draw(_:) (Swift) | drawRect: (Objective-C) |
|---|---|---|
| Signature | override func draw(_ rect: CGRect) | - (void)drawRect:(CGRect)rect |
| Pemanggilan super | super.draw(rect) | [super drawRect:rect] |
| Konteks | UIGraphicsGetCurrentContext() | UIGraphicsGetCurrentContext() |
| Parameter rect | rect: CGRect | CGRect rect |
| Kinerja | Identik | Identik |
Saat migrasi proyek dari Objective-C ke Swift, mengganti nama metode adalah salah satu tugas pertama. Xcode menyediakan konverter otomatis, tetapi drawRect: memerlukan pembaruan manual ke draw(_:). Menurut Apple (2024), versi Swift draw(_:) lebih disukai untuk proyek baru.
draw(_:) dijalankan di CPU, dan implementasi yang tidak optimal dapat menyebabkan penurunan frame dan kinerja rendah. Apple merekomendasikan beberapa pendekatan yang terbukti untuk mempercepat penggambaran.
Setiap operasi Core Graphics (move(to:), addLine(to:), strokePath) memiliki biaya tambahan. Kelompokkan operasi dan gunakan CGPath untuk bentuk kompleks — jalur dibuat sekali dan digunakan kembali di setiap pemanggilan draw(_:).
UIBezierPath — adalah pembungkus Objective-C di sekitar CGPath yang menyediakan API sederhana untuk membuat bentuk. Buat UIBezierPath sebelumnya (misalnya di inisialisator) dan cukup panggil fill() atau stroke() di dalam draw(_:).
private let starPath: UIBezierPath = {
let path = UIBezierPath()
// Membangun bentuk bintang
path.move(to: CGPoint(x: 50, y: 0))
for i in 1...5 {
let angle = CGFloat(i) * 4 * CGFloat.pi / 5
path.addLine(to: CGPoint(x: 50 + 40 * cos(angle),
y: 50 + 40 * sin(angle)))
}
path.close()
return path
}()
override func draw(_ rect: CGRect) {
UIColor.systemYellow.setFill()
starPath.fill()
}
Pengembang sering melakukan kesalahan yang sama saat melakukan override draw(_:). Pengetahuan tentang pola-pola ini membantu menghindari bug dan penurunan kinerja. Mari kita lihat masalah yang paling umum dan solusinya.
Dengan mengikuti aturan ini, Anda akan memastikan penggambaran view kustom yang stabil dan cepat di proyek iOS mana pun. Profil-lah draw(_:) melalui Instruments (Core Animation) untuk melihat waktu eksekusi nyata dan titik lemah.
Pertanyaan yang Sering Diajukan
Tidak, pemanggilan langsung draw(_:) dilarang oleh dokumentasi Apple. Sistem sendiri yang mengelola siklus penggambaran. Untuk meminta penggambaran ulang, gunakan setNeedsDisplay(), yang dengan benar menandai view sebagai memerlukan pembaruan pada siklus rendering terdekat.
Secara fungsional metode ini identik. drawRect: digunakan di Objective-C, draw(_:) di Swift. Keduanya menerima CGRect dari area penggambaran ulang dan menggunakan konteks Core Graphics yang sama melalui UIGraphicsGetCurrentContext().
Apple mengoptimalkan rendering: jika UIView tidak memiliki override draw(_:), sistem tidak membuat konteks bitmap untuknya. Ini menghemat memori. Jika override ada tetapi metode tidak dipanggil — periksa apakah frame view tidak nol dan view terlihat.
Hanya saat diperlukan: rendering pertama, setelah setNeedsDisplay(), saat bounds berubah dengan contentMode = .redraw. Dalam keadaan statis, draw(_:) tidak dipanggil lagi, yang menghemat sumber daya CPU dan baterai.
Apple merekomendasikan pemanggilan super.draw(rect) di awal metode yang di-override. Meskipun implementasi UIView saat ini kosong, pemanggilan super memastikan kompatibilitas dengan versi UIKit mendatang dan merupakan praktik yang baik.
Ringkasan
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