Delegate — adalah pola desain di mana satu objek mendelegasikan pelaksanaan tugas ke objek lain melalui protokol dengan metode yang telah ditentukan sebelumnya. Dalam pengembangan iOS, Delegate adalah salah satu pola fundamental Cocoa Touch, yang digunakan untuk notifikasi asinkron tanpa koneksi langsung antara pengirim dan penerima. Menurut Apple Documentation (2025), delegasi diterapkan di Foundation dan UIKit untuk pemrosesan event tabel, permintaan jaringan, dan manajemen lokasi. Pola ini memastikan kopling lemah antar komponen dan penggunaan ulang kode.
Poin Utama
Delegate (delegat) — adalah objek yang mengimplementasikan protokol tertentu dan menerima notifikasi tentang event objek lain. Pola Delegation adalah alternatif dari pewarisan: alih-alih membuat subclass untuk menimpa metode, objek mendelegasikan pemrosesan event ke objek eksternal. Di iOS, delegation diimplementasikan melalui protokol Swift dengan metode wajib dan opsional. Properti delegate selalu dideklarasikan sebagai weak var untuk menghindari referensi siklik antar objek.
Protokol delegate mendefinisikan kontrak interaksi antar objek. Metode wajib harus diimplementasikan oleh delegat, jika tidak kode tidak akan dikompilasi. Metode opsional ditandai dengan atribut @objc optional dan memungkinkan delegat hanya bereaksi terhadap event yang diperlukan. Nama metode mengikuti konvensi: parameter pertama — objek pengirim, kedua — data event. Misalnya, tableView(_:didSelectRowAt:) menunjukkan bahwa pengirimnya adalah UITableView, dan datanya adalah indeks baris yang dipilih.
// Protokol Delegate
protocol DownloadManagerDelegate: AnyObject {
func downloadManager(_ manager: DownloadManager,
didFinishWith data: Data)
func downloadManager(_ manager: DownloadManager,
didFailWith error: Error)
@objc optional func downloadManager(_ manager: DownloadManager,
didUpdateProgress progress: Float)
}
// Kelas yang menggunakan Delegate
class DownloadManager {
weak var delegate: DownloadManagerDelegate?
func startDownload(from url: URL) {
URLSession.shared.dataTask(with: url) { [weak self] data, _, error in
guard let self else { return }
if let error = error {
self.delegate?.downloadManager(self, didFailWith: error)
} else if let data = data {
self.delegate?.downloadManager(self, didFinishWith: data)
}
}.resume()
}
}
Properti delegate harus dideklarasikan sebagai weak var (pointer lemah) untuk mencegah retain cycle. Jika referensi kuat, delegat dan objek pendelegasi akan saling memegang, dan ARC tidak dapat membebaskan memori mereka. Protokol delegate mewarisi AnyObject (hanya untuk kelas), yang memungkinkan penggunaan weak. Struktur dan enum tidak bisa menjadi delegat karena semantik nilai. Alternatif untuk value types — callback closures.
class ViewController: DownloadManagerDelegate {
let manager = DownloadManager()
override func viewDidLoad() {
super.viewDidLoad()
manager.delegate = self // weak — tidak ada retain cycle
manager.startDownload(from: url)
}
func downloadManager(_ manager: DownloadManager, didFinishWith data: Data) {
processData(data)
}
func downloadManager(_ manager: DownloadManager, didFailWith error: Error) {
showError(error)
}
}
Pola Delegate bekerja dengan prinsip “satu-ke-satu”: satu objek pengirim hanya dapat memiliki satu delegat pada waktu tertentu. Ketika event terjadi, pengirim memeriksa apakah delegate telah diatur dan memanggil metode protokol yang sesuai. Keuntungan dibandingkan panggilan langsung — pengirim tidak tahu tipe delegat, hanya bahwa ia sesuai dengan protokol. Ini mematuhi prinsip inversi ketergantungan (DIP) dari SOLID.
Delegat diatur melalui penugasan: someObject.delegate = self. Saat dealokasi delegat, properti secara otomatis menjadi nil karena semantik weak. Sebelum memanggil metode delegate, diperiksa melalui optional chaining: delegate?.method(). Jika delegate nil — panggilan diabaikan tanpa crash. Untuk metode opsional protokol, digunakan pemeriksaan tambahan: delegate?.responds(to: #selector(...)), meskipun di Swift pemeriksaan ini biasanya implisit melalui deklarasi metode opsional.
Di lingkungan multi-thread, delegate digunakan untuk pengembalian hasil asinkron. URLSession menyediakan URLSessionDelegate dengan metode yang dipanggil saat menerima data, timeout, atau error autentikasi. Metode delegate dijalankan di antrian latar belakang URLSession, sehingga diperlukan dispatch ke main queue untuk pembaruan UI. Delegate asinkron tidak memblokir thread pemanggil, memungkinkan kelanjutan tugas lain.
class NetworkService: NSObject, URLSessionDataDelegate {
private lazy var session = URLSession(
configuration: .default,
delegate: self,
delegateQueue: OperationQueue()
)
private var receivedData = Data()
func urlSession(_ session: URLSession,
dataTask: URLSessionDataTask,
didReceive data: Data) {
receivedData.append(data)
let progress = Float(receivedData.count) / Float(expectedSize)
DispatchQueue.main.async {
self.progressHandler?(progress)
}
}
func urlSession(_ session: URLSession,
task: URLSessionTask,
didCompleteWithError error: Error?) {
if let error = error {
delegate?.networkService(self, didFailWith: error)
} else {
delegate?.networkService(self, didReceive: receivedData)
}
}
}
Delegate dan Callback memecahkan tugas yang sama — notifikasi asinkron — tetapi dengan cara berbeda. Delegate menggunakan protokol dengan metode bernama, callback — closure dengan penangkapan konteks. Pilihan tergantung pada jumlah event, kompleksitas tanda tangan, dan preferensi arsitektur. Apple merekomendasikan delegate untuk API dengan banyak event (UITableView — 20+ metode) dan callback untuk penyelesaian satu kali.
Delegate lebih disukai ketika perlu memproses beberapa event berbeda dari satu sumber. Misalnya, CLLocationManager memberi tahu delegat tentang perubahan lokasi, error izin, masuk/keluar dari zona geografis, dan perubahan status layanan. Setiap event adalah metode protokol terpisah dengan nama yang jelas dan parameter yang diketik. Delegate juga nyaman untuk konfigurasi perilaku (metode should, will, did).
Callback lebih sederhana untuk permintaan satu kali dengan satu hasil. Completion handler di URLSession.dataTask hanya satu baris di titik panggilan dibandingkan setidaknya tiga metode protokol. Callback juga lebih alami untuk rantai fungsional (map, flatMap, async/await). Namun, ketika bersarang lebih dari 2-3 level, callback berubah menjadi Callback Hell, sementara delegate selalu tetap datar.
iOS SDK berisi puluhan protokol delegate bawaan untuk berbagai subsistem. Masing-masing dirancang untuk skenario interaksi tertentu. Menurut Apple Documentation (2025), delegate yang paling sering digunakan adalah UITableViewDelegate, UITextFieldDelegate, CLLocationManagerDelegate, URLSessionDelegate, dan UNUserNotificationCenterDelegate. Protokol ini berisi 3 hingga 30 metode dengan tingkat kewajiban yang berbeda.
UITableViewDelegate mengelola tampilan dan perilaku sel tabel. Berisi metode untuk pemrosesan pemilihan baris, pengaturan tinggi sel, tampilan header/footer kustom, dan aksi geser. Semua metode protokol bersifat opsional, memungkinkan implementasi hanya fungsionalitas yang diperlukan. Jika tidak ada delegat, tabel bekerja dengan pengaturan default. Secara historis, delegate digabungkan dengan UITableViewDataSource.
URLSessionDelegate menyediakan kontrol detail atas permintaan HTTP. Metode delegat dipanggil saat menerima respons server, data, penyelesaian unduhan. Subprotokol khusus URLSessionTaskDelegate dan URLSessionDataDelegate memperluas fungsionalitas dasar untuk jenis tugas tertentu. Delegate diperlukan untuk mendukung unduhan latar belakang, sertifikat SSL, dan pemrosesan pengalihan kustom.
| Delegate | Metode | Tujuan |
|---|---|---|
| UITableViewDelegate | 25 | Tampilan dan interaksi dengan tabel |
| UITextFieldDelegate | 8 | Pemrosesan input teks dan keyboard |
| CLLocationManagerDelegate | 12 | Pembaruan lokasi dan zona geografis |
| URLSessionDelegate | 6 | Manajemen sesi HTTP dan sertifikat |
| UNUserNotificationCenterDelegate | 4 | Pemrosesan notifikasi push di latar depan |
Manajemen memori adalah aspek kritis dalam bekerja dengan delegate di iOS. ARC (Automatic Reference Counting) secara otomatis mengelola memori, tetapi hanya dengan penggunaan referensi weak/unowned yang benar. Pelanggaran aturan menyebabkan kebocoran memori atau dealokasi prematur. Delegate yang dideklarasikan sebagai strong membuat retain cycle jika pemilik delegat juga menyimpan referensi ke objek pendelegasi.
Retain cycle terjadi ketika objek A (pemilik) menetapkan dirinya sebagai delegat objek B, dan B menyimpan referensi kuat ke delegate. Contoh: ViewController membuat URLSession, menetapkan self sebagai delegat sesi, tetapi URLSession secara default menyimpan referensi kuat ke delegate jika delegateQueue tidak ditentukan. Solusi — selalu periksa dokumentasi API untuk jenis referensi ke delegate (weak atau strong) dan secara eksplisit atur delegate ke nil di deinit.
class SafeViewController: UIViewController {
private var session: URLSession?
private var service: NetworkService?
override func viewDidLoad() {
super.viewDidLoad()
service = NetworkService()
service?.delegate = self
}
deinit {
// Mengatur delegate ke nil di deinit — best practice
service?.delegate = nil
session?.invalidateAndCancel()
}
}
// URLSession dengan weak delegate melalui NSObject
class WeakDelegateSession: NSObject {
private weak var delegate: URLSessionDelegate?
func createSession() -> URLSession {
let queue = OperationQueue()
queue.maxConcurrentOperationCount = 1
return URLSession(
configuration: .default,
delegate: self,
delegateQueue: queue
)
}
}
Sebelum memanggil metode delegat, perlu diperiksa bahwa delegat ada (tidak nil) dan mengimplementasikan metode yang dipanggil. Untuk metode wajib protokol, pemeriksaan tidak diperlukan — kompiler menjamin implementasi. Untuk metode opsional gunakan respond(to:) atau optional chaining. Jika delegat telah didealokasi, referensi weak secara otomatis menjadi nil, dan panggilan delegat diabaikan. Ini adalah perilaku aman yang tidak memerlukan pemrosesan tambahan.
Pengembang sering melakukan kesalahan saat bekerja dengan pola Delegate, terutama pada tahap awal mempelajari iOS. Yang paling umum: retain cycle karena strong delegate, lupa memanggil delegate?.method(), tanda tangan metode protokol yang salah, mengatur delegate setelah memulai operasi, dan tabrakan multi-thread. Mari kita lihat setiap kesalahan dan cara pencegahannya.
Kesalahan paling kritis — mendeklarasikan properti delegate sebagai strong var bukan weak var. Ini menciptakan retain cycle di mana baik delegat maupun objek pendelegasi tidak dapat dibebaskan. Konsekuensi: kebocoran memori, perlambatan aplikasi, dan bug tersembunyi. Solusi: selalu gunakan weak var untuk delegate, dan warisi protokol dari AnyObject untuk mengecualikan penggunaan value types sebagai delegat.
Jika delegate diatur setelah memanggil metode asinkron, event pertama mungkin hilang. Contoh: memanggil startDownload() sebelum penugasan manager.delegate = self menyebabkan hilangnya callback penyelesaian, jika unduhan dilakukan secara sinkron atau sangat cepat. Solusi: atur delegate sebelum memanggil metode asinkron dan dokumentasikan urutan inisialisasi dalam komentar protokol.
Pertanyaan yang Sering Diajukan
Weak mencegah retain cycle antara delegat dan objek pendelegasi. Jika referensi kuat, objek akan saling memegang, dan ARC tidak dapat membebaskannya. Referensi weak secara otomatis menjadi nil saat dealokasi delegat. Ini adalah praktik standar Cocoa Touch sejak kemunculan Objective-C dan dipertahankan di Swift untuk kompatibilitas mundur.
Delegate memproses event dan mengelola perilaku (tinggi sel, reaksi terhadap klik). DataSource menyediakan data untuk ditampilkan (jumlah baris, sel). Delegate menjawab pertanyaan “bagaimana?”, dataSource — pertanyaan “apa?”. Di iOS, keduanya diimplementasikan melalui protokol, seringkali di controller yang sama, tetapi secara konseptual terpisah.
Tidak, jika protokol mewarisi AnyObject (protokol kelas). Referensi weak hanya tersedia untuk reference types (kelas). Untuk value types (struct, enum) gunakan callback closure atau kelas wrapper terpisah. Jika Anda mengontrol protokol, Anda dapat tidak mewarisi AnyObject, tetapi maka weak dilarang — pilih secara sadar antara weak-delegate dan struct-delegat.
responds(to:) — metode NSObjectProtocol yang memeriksa apakah objek mengimplementasikan selektor yang ditentukan. Digunakan untuk memeriksa metode opsional @objc protokol sebelum dipanggil. Tanpa pemeriksaan ini, memanggil metode opsional yang tidak diimplementasikan akan menyebabkan NSInvalidArgumentException. Di Swift untuk protokol dengan @objc optional, pemeriksaan bisa implisit melalui optional binding.
Tidak, delegate adalah pola delegasi, bukan singleton. Tidak seperti singleton, delegat dapat diganti saat runtime dan ada dalam satu instance untuk setiap objek pendelegasi. Satu objek dapat menjadi delegat untuk beberapa pengirim. Singleton adalah pola kreasi yang menjamin instance tunggal dari suatu kelas dan tidak ada hubungannya dengan delegasi.
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