Delegate — bu bir ob'ekt vazifani bajarishni boshqa ob'ektga topshiradigan dizayn namunasidir. iOS-da ushbu namuna Swift protokollari va @protocol Objective-C orqali amalga oshiriladi. Delegation Cocoa Touch-ning asosiy namunalaridan biri bo'lib, UITableViewDelegate, UITextFieldDelegate va yuzlab boshqa Apple API-larida qo'llaniladi. Apple Developer Documentation (2025) ma'lumotlariga ko'ra, UIKit tizim sinflarining taxminan 70% meros olmasdan xatti-harakatni sozlash uchun delegatlardan foydalanadi.
Asosiy ma'lumotlar
Delegate — bu ob'ektga o'z vazifalarining bir qismini boshqa ob'ektga o'tkazishga imkon beradigan xulq-atvor dizayn namunasidir. Meros olishdan farqli o'laroq, bunda bola sinf ota-ona metodlarini bekor qilmaydi, delegat kompozitsiyadan foydalanadi: egalik qiluvchi ob'ekt delegatga havolani saqlaydi va ma'lum nuqtalarda uning metodlarini chaqiradi.
Delegat protokolni — delegat bajarishi mumkin bo'lgan metodlar to'plamini belgilaydi. Metodlar majburiy (required) va ixtiyoriy (optional)ga bo'linadi. Swift da protokolning ixtiyoriy metodlari @objc optional kalit so'zi bilan belgilanadi.
A ob'ekti (egalik qiluvchi) delegate xususiyatini — B ob'ektiga (delegat) weak-havolani saqlaydi. Hodisa sodir bo'lganda, A tekshiradi: B protokolning tegishli metodini bajaradimi va uni chaqiradi. Weak-havola majburiydir: usiz delegat xotiradan bo'shatilmaydi, chunki egalik qiluvchi uni kuchli havola bilan ushlab turadi.
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)
// asinxron yuklash
}
}DataLoader sinfi LoaderDelegate protokolini belgilaydi va yuklash hayotiy siklining asosiy nuqtalarida delegat metodlarini chaqiradi. AnyObject protokol faqat sinflar tomonidan bajarilishini kafolatlaydi — bu weak-havola uchun zarur.
Delegatni amalga oshirish Swift da uch bosqichni o'z ichiga oladi: protokolni e'lon qilish, egalik qiluvchida weak delegate xususiyatini yaratish va delegat sinfida protokolni bajarish. Validatsiya bilan maxsus UITextField misolida ko'rib chiqaylik.
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("Validatsiya o'tmadi: kirish juda qisqa")
}
}LoginViewController ValidatorDelegate protokolini bajaradi va o'zini textField ning delegati qilib belgilaydi. Har bir matn o'zgarishida ValidatedTextField validate(_:) ni chaqiradi, agar validatsiya muvaffaqiyatsiz bo'lsa — validatorDidFail(_:). Controller View va validatsiya mantig'i o'rtasida vositachi rolini o'ynaydi.
Delegat, bildirishnomalar va closure lar o'rtasida tanlov qabul qiluvchilar soni va komponentlarning bog'liqlik darajasiga bog'liq. Har bir mexanizm ob'ektlar o'rtasidagi aloqa muammosini hal qiladi, ammo turli xil trade-off lar bilan.
| Xarakteristika | Delegate | NotificationCenter | Closure |
|---|---|---|---|
| Aloqa turi | 1:1 | 1:N | 1:1 |
| Bog'liqlik | Zaif (protokol orqali) | Juda zaif (kalit-satr) | O'rta (kontekstni ushlash) |
| Tip xavfsizligi | To'liq | Yo'q (Any?) | To'liq |
| Retain cycle xavfi | Yo'q (weak) | Yo'q | Ha (self ni ushlash) |
| Qachon qo'llaniladi | Bir necha metodli murakkab callback lar | Ko'pchilikni qiziqtiradigan hodisalar | 1-2 callback li oddiy closure lar |
Delegate bir qabul qiluvchiga bog'liq hodisalar seriyasini uzatish kerak bo'lganda optimaldir. NotificationCenter broadcast bildirishnomalari uchun yaxshiroq. Closure — URLSession dagi completion handler kabi oddiy asinxron operatsiyalar uchun.
Objective-C delegatlarni e'lon qilish uchun @protocol va @optional dan foydalanadi. Swift dan farqli o'laroq, protokolning barcha metodlari sukut bo'yicha ixtiyoriydir. Asosiy farq — delegatga xabar yuborishdan oldin respondsToSelector: chaqiruvi, chunki metod bajarilmagan bo'lishi mumkin.
@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];
}
// tasvirni asinxron yuklash
}
@endObjective-C da asosiy farq: ixtiyoriy metodni chaqirishdan oldin respondsToSelector: tekshiruvi zarur. Swift da protokolning ixtiyoriy metodlari bu tekshiruvni bekor qiladi — optional chaining (?.) avtomatik ravishda bajarilmagan holatni boshqaradi.
Delegatlardan foydalanishdagi xatolar xotira oqishiga, ilovaning ishdan chiqishiga va noaniq bug larga olib keladi. Beshta eng keng tarqalgan muammoni ko'rib chiqaylik.
Retain cycle — eng keng tarqalgan xato. Agar delegate xususiyati strong deb e'lon qilinsa va delegat o'z navbatida egalik qiluvchi ob'ektga ega bo'lsa, saqlash silsilasi hosil bo'ladi. Ikkala ob'ekt ham hech qachon xotiradan bo'shatilmaydi. Yechim: Swift da delegatni har doim weak var, Objective-C da @property (weak) deb e'lon qiling.
Agar egalik qiluvchi ob'ekt delegatdan uzoqroq yashasa va havola qolsa, delegat metodini chaqirish EXC_BAD_ACCESS ga olib keladi. Weak-havola bu muammoni avtomatik hal qiladi: delegat bo'shatilgandan so'ng xususiyat nil bo'ladi. Biroq, ko'p oqimli stsenariylarda qo'shimcha ravishda delegatni asosiy oqimda tekshirish tavsiya etiladi.
20+ metodli protokol interfeyslarni ajratish printsipini (ISP) buzadi. UITableViewDelegate taxminan 30 ta ixtiyoriy metodni o'z ichiga oladi — bu tarixiy istisno. O'z protokollaringizda mas'uliyatni bir nechta kichik protokollarga bo'lish yaxshiroq, har biri o'z roli bilan.
Apple ning tizim API lari Delegate namunasidan faol foydalanadi. Har bir iOS ilovasida uchraydigan UIKit dan uchta asosiy misolni ko'rib chiqaylik.
| API | Protokol | Asosiy metodlar |
|---|---|---|
| UITableView | UITableViewDelegate | didSelectRowAt, heightForRowAt, willDisplay |
| UITextField | UITextFieldDelegate | shouldChangeCharactersIn, didBeginEditing, shouldReturn |
| URLSession | URLSessionDelegate | didReceiveChallenge, didCompleteWithError, didBecomeInvalidWithError |
Ushbu protokollarning har biri xatti-harakatning turli jihatlarini amalga oshiradi: UITableViewDelegate tashqi ko'rinish va teginish reaksiyasini boshqaradi, UITextFieldDelegate matn kiritilishini nazorat qiladi, URLSessionDelegate tarmoq hodisalarini qayta ishlaydi. Bu namunaning moslashuvchanligini ko'rsatadi: delegat har qanday mas'uliyat sohasiga moslashtirilishi mumkin.
Tez-tez beriladigan savollar
Delegate xatti-harakat va tashqi ko'rinishni boshqaradi (katak balandligi, teginish reaksiyasi). DataSource ma'lumotlarni taqdim etadi (qatorlar soni, kataklar tarkibi). UITableViewDelegate va UITableViewDataSource — taqdimot va ma'lumotlar uchun mas'uliyatni ajratadigan ikkita alohida protokoldir.
Weak-havola retain cycle ning oldini oladi. Egalik qiluvchi (masalan, UITableView) delegatga faqat weak sifatida havola saqlaydi. Agar delegat (UIViewController) jadvalga ega bo'lsa, delegatga kuchli havola silsila hosil qiladi: ViewController → UITableView → Delegate (ViewController). Weak bu silsilani uzadi.
SwiftUI da Delegate namunasi kamroq qo'llaniladi — uni @Binding, @State va closure lar almashtiradi. Biroq, delegate UIViewRepresentable orqali UIKit integratsiyasi uchun hali ham qo'llaniladi. Masalan, MKMapViewDelegate va WKUIDelegate UIKit komponentlarini SwiftUI ga o'rashda dolzarb bo'lib qoladi.
@objc optional Swift protokolidagi ixtiyoriy metodlarni e'lon qilish imkonini beradi. Bu Objective-C runtime bilan moslik mexanizmidir. @objc bo'lmasa, Swift protokoli barcha metodlari sukut bo'yicha majburiydir. Optional UIKit protokollarida qo'llaniladi, bu erda delegat faqat o'ziga kerakli metodlarni bajarishi mumkin.
Bitta ob'ekt har bir delegate xususiyati uchun faqat bitta delegatga ega bo'lishi mumkin. Bir nechta ob'ektni xabardor qilish kerak bo'lsa, multicast delegate, delegatlar massivi yoki NotificationCenter dan foydalaning. Delegate namunasi aslida 1:1 munosabati sifatida yaratilgan.
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.