Delegate — adalah pola desain di mana satu objek mendelegasikan pelaksanaan tugas ke objek lain. Di iOS, pola ini diimplementasikan melalui protokol Swift dan @protocol Objective-C. Delegation adalah salah satu pola fundamental Cocoa Touch, yang digunakan di UITableViewDelegate, UITextFieldDelegate, dan ratusan API Apple lainnya. Menurut Apple Developer Documentation (2025), sekitar 70% kelas sistem UIKit menggunakan delegat untuk menyesuaikan perilaku tanpa pewarisan.
Poin Utama
Delegate — adalah pola desain perilaku yang memungkinkan suatu objek mentransfer sebagian tanggung jawabnya ke objek lain. Berbeda dengan pewarisan, di mana kelas anak menimpa metode induk, delegat menggunakan komposisi: objek-pemilik menyimpan referensi ke delegat dan memanggil metodenya di titik-titik tertentu.
Delegat mendefinisikan protokol — serangkaian metode yang dapat diimplementasikan oleh delegat. Metode dibagi menjadi wajib (required) dan opsional (optional). Di Swift, metode opsional protokol ditandai dengan kata kunci @objc optional.
Objek A (pemilik) memiliki properti delegate — referensi weak ke objek B (delegat). Ketika suatu peristiwa terjadi, A memeriksa apakah B mengimplementasikan metode protokol yang sesuai dan memanggilnya. Referensi weak wajib: tanpanya, delegat tidak dapat dibebaskan dari memori, karena pemilik menyimpannya dengan referensi kuat.
protocol LoaderDelegate: AnyObject {
func loaderDidStart(_ loader: DataLoader)
func loader(_ loader: DataLoader, didLoad data: Data)
func loader(_ loader: DataLoader, didFailWith error: Error)
}
class DataLoader {
weak var delegate: LoaderDelegate?
func start() {
delegate?.loaderDidStart(self)
// pemuatan asinkron
}
}Kelas DataLoader mendefinisikan protokol LoaderDelegate dan memanggil metode delegat di titik-titik kunci siklus hidup pemuatan. AnyObject menjamin bahwa protokol hanya dapat diimplementasikan oleh kelas — ini diperlukan untuk referensi weak.
Implementasi delegat di Swift mencakup tiga langkah: mendeklarasikan protokol, membuat properti weak delegate di pemilik, dan mengimplementasikan protokol di kelas-delegat. Mari kita lihat contoh UITextField kustom dengan validasi.
protocol ValidatorDelegate: AnyObject {
func validate(_ input: String) -> Bool
func validatorDidFail(_ input: String)
}
class ValidatedTextField: UITextField {
weak var validator: ValidatorDelegate?
override func textDidChange() {
guard let text = self.text else { return }
if validator?.validate(text) == false {
validator?.validatorDidFail(text)
self.layer.borderColor = UIColor.red.cgColor
}
}
}
class LoginViewController: UIViewController, ValidatorDelegate {
let textField = ValidatedTextField()
override func viewDidLoad() {
super.viewDidLoad()
textField.validator = self
}
func validate(_ input: String) -> Bool {
return input.count >= 6
}
func validatorDidFail(_ input: String) {
print("Validasi gagal: masukan terlalu pendek")
}
}LoginViewController mengimplementasikan protokol ValidatorDelegate dan menetapkan dirinya sebagai delegat textField. Setiap kali teks berubah, ValidatedTextField memanggil validate(_:), dan jika validasi gagal — validatorDidFail(_:). Controller bertindak sebagai perantara antara View dan logika validasi.
Pilihan antara delegat, notifikasi, dan closure tergantung pada jumlah penerima dan tingkat kopling komponen. Setiap mekanisme memecahkan masalah komunikasi antar objek, tetapi dengan trade-off yang berbeda.
| Karakteristik | Delegate | NotificationCenter | Closure |
|---|---|---|---|
| Tipe koneksi | 1:1 | 1:N | 1:1 |
| Kopling | Lemah (melalui protokol) | Sangat lemah (string-kunci) | Sedang (menangkap konteks) |
| Keamanan tipe | Lengkap | Tidak ada (Any?) | Lengkap |
| Risiko retain cycle | Tidak (weak) | Tidak | Ya (menangkap self) |
| Kapan digunakan | Callback kompleks dengan banyak metode | Peristiwa yang menarik banyak pihak | Closure sederhana dengan 1-2 callback |
Delegate optimal ketika perlu mengirim serangkaian peristiwa terkait ke satu penerima. NotificationCenter lebih baik untuk notifikasi broadcast. Closure — untuk operasi asinkron sederhana, seperti completion handler di URLSession.
Objective-C menggunakan @protocol dan @optional untuk mendeklarasikan delegat. Berbeda dengan Swift, semua metode protokol secara default opsional. Perbedaan utama — pemanggilan respondsToSelector: sebelum mengirim pesan ke delegat, karena metode mungkin tidak diimplementasikan.
@protocol ImageCacheDelegate
@optional
- (void)cacheDidStartDownload: (ImageCache *)cache;
- (void)cache: (ImageCache *)cache didCacheImage: (UIImage *)image;
@required
- (void)cache: (ImageCache *)cache didFailWithError: (NSError *)error;
@end
@interface ImageCache : NSObject
@property (nonatomic, weak) id<ImageCacheDelegate> delegate;
- (void)downloadImageAtURL: (NSURL *)url;
@end
@implementation ImageCache
- (void)downloadImageAtURL: (NSURL *)url {
if ([self.delegate respondsToSelector:@selector(cacheDidStartDownload:)]) {
[self.delegate cacheDidStartDownload:self];
}
// pemuatan gambar asinkron
}
@endPerbedaan utama di Objective-C: sebelum memanggil metode opsional, diperlukan pemeriksaan respondsToSelector:. Di Swift, metode opsional protokol menghilangkan pemeriksaan ini — optional chaining (?.) secara otomatis menangani kasus tidak adanya implementasi.
Kesalahan penggunaan delegat menyebabkan kebocoran memori, crash aplikasi, dan bug yang tidak jelas. Mari kita lihat lima masalah paling umum.
Retain cycle — kesalahan paling umum. Jika properti delegate dideklarasikan sebagai strong, dan delegat pada gilirannya memiliki objek-pemilik, terbentuklah siklus retensi. Kedua objek tidak akan pernah dibebaskan dari memori. Solusi: selalu deklarasikan delegat sebagai weak var di Swift atau @property (weak) di Objective-C.
Jika objek-pemilik bertahan lebih lama dari delegat dan referensi tetap ada, pemanggilan metode delegat akan menyebabkan EXC_BAD_ACCESS. Referensi weak menyelesaikan masalah ini secara otomatis: setelah delegat dibebaskan, properti menjadi nil. Namun, dalam skenario multi-thread, sebaiknya periksa delegat di thread utama juga.
Protokol dengan lebih dari 20 metode melanggar prinsip pemisahan antarmuka (ISP). UITableViewDelegate berisi sekitar 30 metode opsional — ini adalah pengecualian historis. Dalam protokol Anda sendiri, lebih baik membagi tanggung jawab menjadi beberapa protokol kecil, masing-masing dengan perannya sendiri.
API sistem Apple secara aktif menggunakan pola Delegate. Mari kita lihat tiga contoh utama dari UIKit yang muncul di setiap aplikasi iOS.
| API | Protokol | Metode utama |
|---|---|---|
| UITableView | UITableViewDelegate | didSelectRowAt, heightForRowAt, willDisplay |
| UITextField | UITextFieldDelegate | shouldChangeCharactersIn, didBeginEditing, shouldReturn |
| URLSession | URLSessionDelegate | didReceiveChallenge, didCompleteWithError, didBecomeInvalidWithError |
Masing-masing protokol ini mengimplementasikan aspek perilaku yang berbeda: UITableViewDelegate mengelola tampilan dan reaksi terhadap sentuhan, UITextFieldDelegate mengontrol input teks, URLSessionDelegate memproses peristiwa jaringan. Ini menunjukkan fleksibilitas pola: delegat dapat disesuaikan dengan bidang tanggung jawab apa pun.
Pertanyaan yang Sering Diajukan
Delegate mengelola perilaku dan tampilan (tinggi sel, reaksi terhadap sentuhan). DataSource menyediakan data (jumlah baris, konten sel). UITableViewDelegate dan UITableViewDataSource — ini adalah dua protokol terpisah yang membagi tanggung jawab untuk presentasi dan data.
Referensi weak mencegah retain cycle. Pemilik (misalnya, UITableView) menyimpan referensi ke delegat hanya sebagai weak. Jika delegat (UIViewController) memiliki tabel, referensi strong ke delegat akan membuat siklus: ViewController → UITableView → Delegate (ViewController). Weak memutus siklus ini.
Di SwiftUI, pola Delegate lebih jarang digunakan — digantikan oleh @Binding, @State, dan closure. Namun, delegate masih digunakan untuk integrasi UIKit melalui UIViewRepresentable. Misalnya, MKMapViewDelegate dan WKUIDelegate tetap relevan saat membungkus komponen UIKit ke dalam SwiftUI.
@objc optional memungkinkan mendeklarasikan metode opsional dalam protokol Swift. Ini adalah mekanisme kompatibilitas dengan Objective-C runtime. Tanpa @objc, semua metode protokol Swift secara default wajib. Optional digunakan dalam protokol UIKit, di mana delegat hanya dapat mengimplementasikan metode yang diperlukan.
Satu objek dapat memiliki hanya satu delegat untuk setiap properti delegate. Jika perlu memberi tahu beberapa objek, gunakan multicast delegate, array delegat, atau NotificationCenter. Pola Delegate pada dasarnya dirancang sebagai hubungan 1:1.
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