Delegate — bu bir ob'ekt vazifalarni bajarishni oldindan belgilangan metodlari bo'lgan protokol orqali boshqa ob'ektga topshiradigan dizayn namunasidir. iOS dasturiy ta'minotida Delegate Cocoa Touch-ning asosiy namunalaridan biri bo'lib, jo'natuvchi va qabul qiluvchi o'rtasida to'g'ridan-to'g'ri bog'lanishsiz asinxron xabardor qilish uchun ishlatiladi. Apple Documentation (2025) ma'lumotlariga ko'ra, delegatsiya Foundation va UIKit-da jadval hodisalari, tarmoq so'rovlari va joylashuvni boshqarish uchun qo'llaniladi. Namuna komponentlarning zaif bog'lanishini va kodning qayta ishlatilishini ta'minlaydi.
Asosiy fikrlar
Delegate (delegat) — ma'lum bir protokolni amalga oshiradigan va boshqa ob'ektning hodisalari haqida bildirishnomalar oladigan ob'ektdir. Delegation namunasi meros olishga alternativadir: metodlarni bekor qilish uchun pastki sinf yaratish o'rniga, ob'ekt hodisalarni qayta ishlashni tashqi ob'ektga topshiradi. iOS-da delegation majburiy va ixtiyoriy metodlari bo'lgan Swift protokollari orqali amalga oshiriladi. delegate xususiyati har doim weak var sifatida e'lon qilinadi, bu ob'ektlar o'rtasida tsiklik havolalarning oldini olish uchun.
Delegate protokoli ob'ektlar o'rtasidagi o'zaro ta'sir shartnomasini belgilaydi. Majburiy metodlar delegat tomonidan amalga oshirilishi kerak, aks holda kod kompilyatsiya qilinmaydi. Ixtiyoriy metodlar @objc optional atributi bilan belgilanadi va delegatga faqat kerakli hodisalarga reaksiya berish imkonini beradi. Metod nomlari konvensiyaga amal qiladi: birinchi parametr — jo'natuvchi ob'ekt, ikkinchi — hodisa ma'lumotlari. Masalan, tableView(_:didSelectRowAt:) jo'natuvchi UITableView ekanligini va ma'lumotlar tanlangan qator indeksi ekanligini ko'rsatadi.
// Delegate Protokoli
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)
}
// Delegate ishlatadigan sinf
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()
}
}
delegate xususiyati retain cycle oldini olish uchun weak var (zaif ko'rsatkich) sifatida e'lon qilinishi kerak. Agar havola kuchli bo'lsa, delegat va delegatsiya qiluvchi ob'ekt bir-birini ushlab turardi va ARC ularning xotirasini bo'shata olmadi. Delegate protokollari AnyObject-dan (faqat sinflar uchun) meros oladi, bu weak dan foydalanish imkonini beradi. Strukturalar va enum qiymat semantikasi tufayli delegat bo'la olmaydi. Value types uchun muqobil — callback closure-lar.
class ViewController: DownloadManagerDelegate {
let manager = DownloadManager()
override func viewDidLoad() {
super.viewDidLoad()
manager.delegate = self // weak — retain cycle yo'q
manager.startDownload(from: url)
}
func downloadManager(_ manager: DownloadManager, didFinishWith data: Data) {
processData(data)
}
func downloadManager(_ manager: DownloadManager, didFailWith error: Error) {
showError(error)
}
}
Delegate namunasi “bir-birga” prinsipi bilan ishlaydi: bitta jo'natuvchi ob'ekt ma'lum bir vaqtda faqat bitta delegatga ega bo'lishi mumkin. Hodisa sodir bo'lganda, jo'natuvchi delegate o'rnatilganligini tekshiradi va protokolning tegishli metodini chaqiradi. Afzallik to'g'ridan-to'g'ri chaqiruvdan farqli o'laroq — jo'natuvchi delegatning turini bilmaydi, faqat u protokolga mos kelishini biladi. Bu SOLID-dan bog'liqliklarni teskari o'zgartirish printsipiga (DIP) mos keladi.
Delegat tayinlash orqali o'rnatiladi: someObject.delegate = self. Delegatning dealokatsiyasi vaqtida xususiyat weak semantikasi tufayli avtomatik ravishda nil bo'ladi. delegate metodini chaqirishdan oldin optional chaining orqali tekshiriladi: delegate?.method(). Agar delegate nil bo'lsa — chaqiruv crashsiz e'tiborga olinmaydi. Protokolning ixtiyoriy metodlari uchun qo'shimcha tekshiruv ishlatiladi: delegate?.responds(to: #selector(...)), Swift-da bu tekshiruv odatda ixtiyoriy metod deklaratsiyasi orqali yashirin tarzda amalga oshiriladi.
Ko'p oqimli muhitda delegate natijani asinxron qaytarish uchun ishlatiladi. URLSession ma'lumot olinganda, vaqt tugashida yoki autentifikatsiya xatosida chaqiriladigan metodlari bo'lgan URLSessionDelegate ni taqdim etadi. Delegate metodlari URLSession fon navbatida bajariladi, shuning uchun UI yangilanishlari uchun main queue-ga dispetcherizatsiya talab qilinadi. Asinxron delegate chaqiruvchi oqimni bloklamaydi, boshqa vazifalarni davom ettirish imkonini beradi.
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 va Callback bir xil vazifani — asinxron xabardor qilishni — hal qiladi, lekin turli usullar bilan. Delegate nomlangan metodlari bo'lgan protokoldan, callback kontekstni ushlab turuvchi closure-dan foydalanadi. Tanlov hodisalar soniga, imzolarning murakkabligiga va arxitektura afzalliklariga bog'liq. Apple ko'p hodisali API-lar uchun delegate (UITableView — 20+ metod), bir martalik yakunlashlar uchun callback ni tavsiya qiladi.
Delegate bir manbadan bir nechta turli hodisalarni qayta ishlash kerak bo'lganda afzalroqdir. Masalan, CLLocationManager delegatga joylashuv o'zgarishi, ruxsat xatolari, geozonalarga kirish/chiqish va xizmat holati o'zgarishi haqida xabar beradi. Har bir hodisa aniq nomi va tipli parametrlari bo'lgan alohida protokol metodidir. Delegate shuningdek xatti-harakatni sozlash uchun qulay (should, will, did metodlari).
Callback bir martalik so'rovlar uchun soddaroqdir. Completion handler URLSession.dataTask da chaqiruv nuqtasida bitta qatorni egallaydi, protokolning kamida uchta metodiga nisbatan. Callback shuningdek funktsional zanjirlar uchun tabiiyroqdir (map, flatMap, async/await). Biroq, 2-3 darajadan ortiq ichki joylashtirishda callback Callback Hell ga aylanadi, delegate esa har doim tekis qoladi.
iOS SDK turli quyi tizimlar uchun o'nlab o'rnatilgan delegate protokollarini o'z ichiga oladi. Ularning har biri ma'lum bir o'zaro ta'sir stsenariysi uchun mo'ljallangan. Apple Documentation (2025) ma'lumotlariga ko'ra, eng ko'p ishlatiladigan delegate-lar UITableViewDelegate, UITextFieldDelegate, CLLocationManagerDelegate, URLSessionDelegate va UNUserNotificationCenterDelegate dir. Bu protokollar turli darajadagi majburiylikka ega 3 dan 30 gacha metodni o'z ichiga oladi.
UITableViewDelegate jadval hujayralarining ko'rinishi va xatti-harakatini boshqaradi. Qator tanlash, hujayra balandligini sozlash, maxsus header/footer ko'rinishlari va surish harakatlari uchun metodlarni o'z ichiga oladi. Protokolning barcha metodlari ixtiyoriy bo'lib, faqat kerakli funksionallikni amalga oshirish imkonini beradi. Delegat bo'lmaganda, jadval standart sozlamalar bilan ishlaydi. Tarixan delegate UITableViewDataSource bilan birlashtirilgan.
URLSessionDelegate HTTP so'rovlari ustida batafsil nazoratni ta'minlaydi. Delegat metodlari server javobi, ma'lumotlar olinganda, yuklab olish tugallanganda chaqiriladi. Ixtisoslashtirilgan quyi protokollar URLSessionTaskDelegate va URLSessionDataDelegate ma'lum vazifa turlari uchun asosiy funksionallikni kengaytiradi. Delegate fon yuklab olishlari, SSL sertifikatlari va maxsus yo'naltirishni qayta ishlash uchun talab qilinadi.
| Delegate | Metodlar | Vazifa |
|---|---|---|
| UITableViewDelegate | 25 | Jadval ko'rinishi va o'zaro ta'siri |
| UITextFieldDelegate | 8 | Matn kiritish va klaviatura qayta ishlash |
| CLLocationManagerDelegate | 12 | Joylashuv yangilanishi va geozonalar |
| URLSessionDelegate | 6 | HTTP sessiyasi va sertifikatlarni boshqarish |
| UNUserNotificationCenterDelegate | 4 | Oldingi planda push bildirishnomalarini qayta ishlash |
Xotirani boshqarish iOS-da delegate bilan ishlashning muhim jihatidir. ARC (Automatic Reference Counting) xotirani avtomatik boshqaradi, lekin faqat weak/unowned havolalardan to'g'ri foydalanish bilan. Qoidalarni buzish xotira oqishiga yoki muddatidan oldin dealokatsiyaga olib keladi. Strong sifatida e'lon qilingan delegate, agar delegat egasi delegatsiya qiluvchi ob'ektga havolani saqlasa, retain cycle yaratadi.
Retain cycle A ob'ekti (egasi) o'zini B ob'ektining delegati qilib o'rnatganda va B delegate ga kuchli havolani saqlaganda yuzaga keladi. Misol: ViewController URLSession yaratadi, self ni sessiyaning delegati qilib o'rnatadi, lekin URLSession standart bo'yicha delegate ga kuchli havolani saqlaydi, agar delegateQueue ko'rsatilmagan bo'lsa. Yechim — har doim API hujjatlarida delegate ga havola turini (weak yoki strong) tekshiring va deinit da delegate ni aniq nolga tenglashtiring.
class SafeViewController: UIViewController {
private var session: URLSession?
private var service: NetworkService?
override func viewDidLoad() {
super.viewDidLoad()
service = NetworkService()
service?.delegate = self
}
deinit {
// deinit da delegate ni nolga tenglashtirish — best practice
service?.delegate = nil
session?.invalidateAndCancel()
}
}
// NSObject orqali weak delegate bilan URLSession
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
)
}
}
Delegat metodini chaqirishdan oldin delegat mavjudligini (nil emas) va chaqirilayotgan metodni amalga oshirishini tekshirish kerak. Protokolning majburiy metodlari uchun tekshirish talab qilinmaydi — kompilyator amalga oshirilishini kafolatlaydi. Ixtiyoriy metodlar uchun respond(to:) yoki optional chaining dan foydalaning. Agar delegat dealokatsiya qilingan bo'lsa, weak havola avtomatik ravishda nil bo'ladi va delegat chaqiruvi e'tiborga olinmaydi. Bu qo'shimcha ishlov berishni talab qilmaydigan xavfsiz xatti-harakatdir.
Dasturchilar, ayniqsa iOS ni o'rganishning dastlabki bosqichlarida, Delegate namunasi bilan ishlashda tez-tez xato qilishadi. Eng keng tarqalgan: strong delegate sababli retain cycle, delegate?.method() ni chaqirishni unutish, protokol metodlarining noto'g'ri imzosi, operatsiya boshlangandan keyin delegate ni o'rnatish va ko'p oqimli to'qnashuvlar. Keling, har bir xato va uni oldini olish usullarini ko'rib chiqaylik.
Eng muhim xato — delegate xususiyatini weak var o'rniga strong var sifatida e'lon qilish. Bu na delegat, na delegatsiya qiluvchi ob'ekt bo'shatilmaydigan retain cycle yaratadi. Natijalar: xotira oqishi, dasturning sekinlashishi va yashirin xatolar. Yechim: har doim delegate uchun weak var dan foydalaning va protokolni AnyObject dan meros qilib oling, bu value types ni delegat sifatida ishlatishni istisno qiladi.
Agar delegate asinxron metod chaqirilgandan keyin o'rnatilsa, birinchi hodisalar yo'qolishi mumkin. Misol: manager.delegate = self tayinlashdan oldin startDownload() ni chaqirish, yuklab olish sinxron yoki juda tez bo'lsa, yakunlash haqidagi callback ni yo'qotishiga olib keladi. Yechim: asinxron metodni chaqirishdan oldin delegate ni o'rnating va protokol izohlarida inicializatsiya tartibini hujjatlashtiring.
Tez-tez beriladigan savollar
Weak delegat va delegatsiya qiluvchi ob'ekt o'rtasida retain cycle ning oldini oladi. Agar havola strong bo'lsa, ob'ektlar bir-birini ushlab turardi va ARC ularni bo'shata olmadi. Weak-havola delegatning dealokatsiyasi vaqtida avtomatik ravishda nil bo'ladi. Bu Objective-C davridan beri Cocoa Touch ning standart amaliyotidir va orqaga moslik uchun Swift-da saqlangan.
Delegate hodisalarni qayta ishlaydi va xatti-harakatni boshqaradi (hujayra balandligi, bosishlarga reaksiya). DataSource ko'rsatish uchun ma'lumotlarni taqdim etadi (qatorlar soni, hujayralar). Delegate “qanday?” degan savolga, dataSource “nima?” degan savolga javob beradi. iOS-da ikkalasi ham protokollar orqali amalga oshiriladi, ko'pincha bir xil kontrollerda, lekin kontseptual jihatdan ajratilgan.
Yo'q, agar protokol AnyObject dan (sinf protokoli) meros olsa. Weak-havolalar faqat reference types (sinflar) uchun mavjud. Value types (struct, enum) uchun callback closure-lardan yoki alohida o'ram sinfidan foydalaning. Agar protokolni nazorat qilsangiz, AnyObject dan meros olmasligingiz mumkin, lekin unda weak taqiqlangan — weak-delegat va struct-delegat o'rtasida ongli ravishda tanlang.
responds(to:) — NSObjectProtocol metodi, ob'ekt ko'rsatilgan selektorni amalga oshirishini tekshiradi. Chaqirishdan oldin protokolning @objc ixtiyoriy metodlarini tekshirish uchun ishlatiladi. Bu tekshiruvsiz amalga oshirilmagan ixtiyoriy metodni chaqirish NSInvalidArgumentException ga olib keladi. Swift-da @objc optional bo'lgan protokollar uchun tekshiruv optional binding orqali yashirin bo'lishi mumkin.
Yo'q, delegate delegatsiya namunasidir, singleton emas. Singletondan farqli o'laroq, delegat runtime da almashtirilishi mumkin va har bir delegatsiya qiluvchi ob'ekt uchun bitta nusxada mavjud. Bitta ob'ekt bir nechta jo'natuvchilar uchun delegat bo'lishi mumkin. Singleton sinfning yagona nusxasini kafolatlaydigan yaratuvchi namunadir va uning delegatsiyaga aloqasi yo'q.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.