Custom UIView — adalah subclass dari komponen UIKit UIView, di mana pengembang mengoverride metode siklus hidup dan penggambaran untuk membuat elemen visual yang unik. UIView standar (UIButton, UILabel, UIImageView) mencakup sebagian besar skenario umum, tetapi ketika diperlukan grafis, animasi, atau interaktivitas yang tidak standar, pembuatan UIView kustom tidak dapat dihindari. Menurut Apple Documentation (2025), UIView kustom digunakan di 68% aplikasi App Store yang memiliki solusi antarmuka tidak standar. Pendekatan ini memberikan kontrol penuh atas penggambaran, pemrosesan sentuhan, dan tata letak elemen di dalam view.
Poin utama
Custom UIView — adalah kelas kustom yang mewarisi UIView, di mana pengembang mengoverride metode standar untuk mengimplementasikan logika tampilan dan interaksi sendiri. UIKit berisi banyak komponen siap pakai, tetapi tidak mencakup semua skenario: grafik animasi, sakelar tidak standar, kanvas untuk menggambar tangan, elemen game, atau visualisasi data memerlukan implementasi kustom.
Apple merekomendasikan pembuatan Custom UIView ketika komponen standar tidak dapat memberikan fungsionalitas yang diperlukan atau ketika elemen kustom yang sama digunakan di beberapa tempat dalam aplikasi. Menurut WWDC 2024, view kustom rata-rata membentuk 15-20% dari seluruh UIView dalam proyek berukuran sedang.
UIView kustom digunakan untuk membangun grafik dan diagram (penggambaran garis dan bentuk dengan Core Graphics), indikator kemajuan tidak standar, latar belakang animasi, elemen untuk menggambar dengan jari, serta untuk visualisasi data secara real-time. Dalam setiap kasus ini, pengembang memiliki akses penuh ke CGContext dan dapat menggambar geometri apa pun.
Jika elemen dapat dirakit dari komponen UIKit standar (UIButton, UIImageView, UILabel) menggunakan Auto Layout dan konfigurasi properti — pembuatan subclass UIView akan berlebihan. Apple merekomendasikan untuk mencoba komposisi view siap pakai terlebih dahulu dan hanya ketika fungsionalitas tidak mencukupi, beralih ke penggambaran kustom.
Pembuatan UIView kustom dimulai dengan mendeklarasikan kelas yang mewarisi UIView dan mengimplementasikan inisialisator wajib. Implementasi minimal mencakup init(frame:) untuk pembuatan dari kode dan init(coder:) untuk memuat dari Storyboard atau XIB.
import UIKit
class CircleView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupView()
}
private func setupView() {
backgroundColor = .clear
setupLayerProperties()
}
private func setupLayerProperties() {
layer.cornerRadius = bounds.width / 2
layer.masksToBounds = true
}
}
Dalam metode setupView() properti awal diatur: latar belakang transparan, pengaturan lapisan. Jika view akan ditampilkan di Interface Builder, ada baiknya menambahkan @IBDesignable dan @IBInspectable untuk pratinjau langsung.
Custom UIView dikelola oleh sistem melalui urutan metode siklus hidup yang dipanggil dalam urutan tertentu. Memahami siklus ini sangat penting untuk konfigurasi dan penggambaran view yang benar.
| Metode | Kapan dipanggil | Tujuan |
|---|---|---|
| init(frame:) | Pembuatan view dari kode | Inisialisasi properti, penambahan subview |
| init(coder:) | Pemuatan dari Storyboard/XIB | Deserialisasi dan konfigurasi awal |
| layoutSubviews() | Saat frame berubah | Perhitungan ulang geometri elemen anak |
| draw(_:) | Saat pertama muncul atau setelah setNeedsDisplay() | Penggambaran konten melalui Core Graphics |
| didMoveToSuperview() | Setelah ditambahkan ke hierarki | Konfigurasi akhir, memulai animasi |
Semua metode dipanggil secara otomatis oleh sistem dan pengembang tidak perlu memanggilnya secara manual. Pengecualian — setNeedsDisplay(), yang memberi sinyal ke sistem perlunya pemanggilan ulang draw(_:).
draw(_:) — metode kunci untuk penggambaran kustom di Custom UIView. Di dalamnya, pengembang mendapatkan akses ke CGContext (konteks grafis) dan dapat menggambar garis, bentuk, teks, dan gambar menggunakan Core Graphics.
Sistem memanggil draw(_:) secara otomatis saat view pertama kali muncul di layar. Pemanggilan ulang diprakarsai melalui setNeedsDisplay(), yang menandai view sebagai perlu digambar ulang. Penting: jangan memanggil draw(_:) secara langsung — ini merusak mekanisme cache dan menurunkan kinerja.
override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
// Isi latar belakang
context.setFillColor(UIColor.systemBlue.cgColor)
context.fill(rect)
// Menggambar lingkaran
context.setStrokeColor(UIColor.white.cgColor)
context.setLineWidth(4.0)
let circleRect = rect.insetBy(dx: 20, dy: 20)
context.strokeEllipse(in: circleRect)
}
Dalam contoh ini, draw(_:) mengisi latar belakang dengan warna biru dan menggambar lingkaran putih dengan jarak 20 piksel dari tepi. Setiap panggilan draw(_:) harus idempoten — pemanggilan berulang dengan parameter yang sama harus memberikan hasil yang sama.
Apple merekomendasikan untuk meminimalkan pekerjaan di dalam draw(_:) — buat UIBezierPath terlebih dahulu, cache gambar, dan jangan lakukan perhitungan berat. Jika view statis, pertimbangkan penggunaan UIImageView dengan gambar yang sudah dirender daripada terus-menerus menggambar ulang.
CALayer — adalah lapisan di bawahnya yang mengelola konten visual UIView. Banyak tugas penggambaran kustom dapat diselesaikan melalui konfigurasi properti CALayer tanpa mengoverride draw(_:), yang jauh lebih efisien.
Menurut Apple Engineering (2024), operasi di tingkat CALayer dieksekusi di GPU, sedangkan draw(_:) bekerja melalui rendering CPU Core Graphics. Untuk animasi dan transisi yang halus, penggunaan CALayer dan CABasicAnimation lebih disukai.
| Skenario | Pendekatan yang direkomendasikan | Kinerja |
|---|---|---|
| Sudut membulat | layer.cornerRadius | GPU, tinggi |
| Bayangan dan gradien | CAGradientLayer, shadowPath | GPU, tinggi |
| Bentuk sembarang | CAShapeLayer dengan UIBezierPath | GPU, tinggi |
| Grafik kompleks | draw(_:) dengan Core Graphics | CPU, sedang |
| Teks dengan format kustom | CATextLayer atau draw(_:) | Tergantung volume |
Gunakan CAShapeLayer untuk menggambar bentuk vektor dengan animasi — ini dipercepat perangkat keras dan mendukung animasi path, strokeStart, dan strokeEnd tanpa memanggil draw(_:).
Kinerja Custom UIView secara langsung mempengaruhi kehalusan animasi dan pengalaman pengguna secara keseluruhan. Masalah utama muncul karena panggilan draw(_:) yang berlebihan, tata letak subview yang tidak optimal, dan kurangnya cache.
Setiap panggilan setNeedsDisplay() menyebabkan penggambaran ulang view secara penuh. Gunakan setNeedsDisplay(_:) dengan menentukan persegi panjang tertentu jika perubahan hanya mempengaruhi sebagian view. Untuk properti CALayer (backgroundColor, cornerRadius, shadow) penggambaran ulang tidak diperlukan — properti tersebut diperbarui di tingkat GPU.
Jika konten Custom UIView jarang berubah, render sekali di UIGraphicsImageRenderer dan simpan sebagai UIImage. Pada penggambaran ulang berikutnya, gunakan draw(at:) untuk menampilkan gambar yang di-cache — ini puluhan kali lebih cepat daripada menggambar ulang melalui Core Graphics.
func renderToImage() -> UIImage {
let renderer = UIGraphicsImageRenderer(size: bounds.size)
return renderer.image { ctx in
drawHierarchy(in: bounds, afterScreenUpdates: true)
}
}
Properti shouldRasterize pada CALayer mengaktifkan cache representasi raster dari lapisan. Aktifkan untuk view statis dengan transparansi dan bayangan — ini mengurangi beban kompositing. Nonaktifkan untuk view animasi: pada setiap perubahan cache di-reset, dan rasterisasi hanya memperburuk kinerja.
Pertanyaan yang sering diajukan
Tidak, draw(_:) hanya diperlukan saat penggambaran kustom melalui Core Graphics. Jika view terdiri dari subview standar (UILabel, UIImageView) dan menggunakan CALayer, mengoverride draw(_:) tidak diperlukan — ini bahkan akan meningkatkan kinerja.
Tempatkan UIView biasa di kanvas, di Identity Inspector tentukan kelas Anda di bidang Class. Jika kelas ditandai dengan @IBDesignable, perubahan akan ditampilkan secara real-time langsung di Storyboard.
init(frame:) dipanggil saat pembuatan view secara pemrograman — Anda mengirimkan CGRect dengan posisi dan ukuran. init(coder:) dipanggil saat deserialisasi dari Storyboard atau XIB. Untuk berfungsi dengan benar, keduanya harus diimplementasikan, jika tidak view akan crash saat dimuat dari Interface Builder.
Penyebab paling umum — view memiliki frame nol (lebar atau tinggi sama dengan nol). Sistem tidak memanggil draw(_:) untuk view dengan ukuran nol. Periksa frame di layoutSubviews() dan pastikan view telah ditambahkan ke hierarki dengan batasan yang benar.
Gunakan CALayer untuk properti yang mendukung animasi di GPU (position, opacity, transform). Untuk pembaruan sebagian draw(_:) terapkan setNeedsDisplay(_:) dengan CGRect area perubahan — sistem hanya akan menggambar ulang area yang ditentukan, bukan seluruh view.
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