Delegate, bir nesnenin görev yürütmeyi başka bir nesneye devrettiği bir tasarım desenidir. iOS'ta desen, Swift protokolleri ve @protocol Objective-C aracılığıyla uygulanır. Delegasyon, UITableViewDelegate, UITextFieldDelegate ve yüzlerce diğer Apple API'sinde kullanılan Cocoa Touch'ın temel desenlerinden biridir. Apple Developer Documentation'a (2025) göre, UIKit sistem sınıflarının yaklaşık %70'i kalıtım olmadan davranış özelleştirmesi için delegeleri kullanır.
Önemli Noktalar
Delegate, bir nesnenin sorumluluklarının bir kısmını başka bir nesneye devretmesine izin veren bir davranışsal tasarım desenidir. Bir alt sınıfın üst sınıf metotlarını geçersiz kıldığı kalıtımın aksine, delege bileşimi kullanır: sahip nesne, delegeye bir referans tutar ve belirli noktalarda metotlarını çağırır.
Delege bir protokol tanımlar — delegenin uygulayabileceği bir dizi metot. Metotlar zorunlu (required) ve isteğe bağlı (optional) olarak ayrılır. Swift'te, isteğe bağlı protokol metotları @objc optional anahtar sözcüğüyle işaretlenir.
Nesne A (sahip), bir delegate özelliği içerir — B nesnesine (delege) zayıf bir referans. Bir olay meydana geldiğinde, A, B'nin ilgili protokol metodunu uygulayıp uygulamadığını kontrol eder ve çağırır. Zayıf referans zorunludur: onsuz, delege bellekten serbest bırakılamaz çünkü sahip onu güçlü bir referansla tutar.
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)
// asenkron yükleme
}
}DataLoader sınıfı, LoaderDelegate protokolünü tanımlar ve yükleme yaşam döngüsünün önemli noktalarında delege metotlarını çağırır. AnyObject, protokolün yalnızca sınıflar tarafından uygulanabilmesini garanti eder — bu, zayıf referans için gereklidir.
Swift'te delege uygulaması üç adım içerir: protokolü bildirmek, sahipte zayıf bir delegate özelliği oluşturmak ve delege sınıfında protokolü uygulamak. Doğrulama ile özel bir UITextField örneğine bakalım.
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("Doğrulama başarısız: girdi çok kısa")
}
}LoginViewController, ValidatorDelegate protokolünü uygular ve kendisini textField'ın delegesi olarak atar. Her metin değişikliğinde ValidatedTextField, validate(_:) çağırır ve doğrulama başarısız olursa — validatorDidFail(_:). Denetleyici, View ile doğrulama mantığı arasında bir aracı görevi görür.
Delege, bildirimler ve closure'lar arasında seçim, alıcı sayısına ve bileşen bağlantısına bağlıdır. Her mekanizma, nesneler arası iletişim sorununu çözer, ancak farklı ödünleşimlerle.
| Özellik | Delegate | NotificationCenter | Closure |
|---|---|---|---|
| İletişim türü | 1:1 | 1:N | 1:1 |
| Bağlantı | Zayıf (protokol aracılığıyla) | Çok zayıf (dize anahtarı) | Orta (bağlam yakalama) |
| Tür güvenliği | Tam | Yok (Any?) | Tam |
| Retain cycle riski | Hayır (weak) | Hayır | Evet (self yakalama) |
| Ne zaman kullanılır | Birden çok metotlu karmaşık callback'ler | Birçok kişinin ilgilendiği olaylar | 1-2 callback'li basit closure'lar |
Delegate, bir dizi ilgili olayı tek bir alıcıya iletmeniz gerektiğinde idealdir. NotificationCenter yayın bildirimleri için daha iyidir. Closure, URLSession'daki completion handler gibi basit asenkron işlemler içindir.
Objective-C, delegeleri bildirmek için @protocol ve @optional kullanır. Swift'in aksine, tüm protokol metotları varsayılan olarak isteğe bağlıdır. Temel fark, delegeye mesaj göndermeden önce respondsToSelector: çağrısıdır, çünkü metot uygulanmamış olabilir.
@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];
}
// asenkron görsel yükleme
}
@endObjective-C'teki temel fark: isteğe bağlı bir metodu çağırmadan önce respondsToSelector: kontrolü gereklidir. Swift'te, isteğe bağlı protokol metotları bu kontrolü gereksiz kılar — optional chaining (?.) uygulama eksikliğini otomatik olarak işler.
Delege kullanım hataları bellek sızıntılarına, uygulama çökmelerine ve belirsiz hatalara yol açar. En yaygın beş soruna bakalım.
Retain cycle en yaygın hatadır. delegate özelliği strong olarak bildirilmişse ve delege de sahip nesneye sahipse, bir tutma döngüsü oluşur. Her iki nesne de bellekten asla serbest bırakılmaz. Çözüm: her zaman Swift'te weak var veya Objective-C'te @property (weak) olarak delegeyi bildirin.
Sahip nesne, delegeyi geride bırakırsa ve referans kalırsa, delege metodunu çağırmak EXC_BAD_ACCESS ile sonuçlanır. Zayıf referans bu sorunu otomatik olarak çözer: delege serbest bırakıldıktan sonra özellik nil olur. Ancak, çok iş parçacıklı senaryolarda, ana iş parçacığında ek olarak delegeyi kontrol etmelisiniz.
20'den fazla metodu olan bir protokol, Arayüz Ayrımı Prensibi'ni (ISP) ihlal eder. UITableViewDelegate yaklaşık 30 isteğe bağlı metot içerir — bu tarihsel bir istisnadır. Kendi protokollerinizde, sorumluluğu her biri kendi rolüne sahip birkaç küçük protokole bölmek daha iyidir.
Apple'ın sistem API'leri Delegate desenini aktif olarak kullanır. Her iOS uygulamasında görünen UIKit'ten üç temel örneğe bakalım.
| API | Protokol | Temel Metotlar |
|---|---|---|
| UITableView | UITableViewDelegate | didSelectRowAt, heightForRowAt, willDisplay |
| UITextField | UITextFieldDelegate | shouldChangeCharactersIn, didBeginEditing, shouldReturn |
| URLSession | URLSessionDelegate | didReceiveChallenge, didCompleteWithError, didBecomeInvalidWithError |
Bu protokollerin her biri farklı davranış yönlerini uygular: UITableViewDelegate görünüm ve dokunma yanıtını yönetir, UITextFieldDelegate metin girişini kontrol eder, URLSessionDelegate ağ olaylarını işler. Bu, desenin esnekliğini gösterir: delege herhangi bir sorumluluk alanına uyarlanabilir.
Sıkça Sorulan Sorular
Delegate davranışı ve görünümü yönetir (hücre yüksekliği, dokunma yanıtı). DataSource veri sağlar (satır sayısı, hücre içerikleri). UITableViewDelegate ve UITableViewDataSource'ta — bunlar, sunum ve veri sorumluluğunu bölen iki ayrı protokoldür.
Zayıf referans retain cycle'ları önler. Sahip (örneğin, UITableView) delegeye yalnızca weak olarak referans tutar. Delege (UIViewController) tabloya sahipse, delegeye güçlü bir referans bir döngü oluşturur: ViewController → UITableView → Delegate (ViewController). Weak bu döngüyü kırar.
SwiftUI'de Delegate deseni daha az kullanılır — yerini @Binding, @State ve closure'lar alır. Ancak, delege UIViewRepresentable aracılığıyla UIKit entegrasyonu için hâlâ kullanılır. Örneğin, MKMapViewDelegate ve WKUIDelegate, UIKit bileşenlerini SwiftUI'ye sararken geçerliliğini korur.
@objc optional, Swift protokolünde isteğe bağlı metotlar bildirmeye izin verir. Bu, Objective-C çalışma zamanıyla bir uyumluluk mekanizmasıdır. @objc olmadan, tüm Swift protokol metotları varsayılan olarak zorunludur. Optional, delegenin yalnızca ihtiyaç duyduğu metotları uygulayabileceği UIKit protokollerinde kullanılır.
Bir nesne, her delegate özelliği için yalnızca bir delegeye sahip olabilir. Birden çok nesneye bildirim yapmanız gerekiyorsa, çok noktaya yayın delege, bir delege dizisi veya NotificationCenter kullanın. Delegate deseni başlangıçta 1:1 ilişki olarak tasarlanmıştır.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun