Delegate: nedir, temsil yetkisi deseni ve iOS'ta nasıl çalışır

Yazar: IT Sectr Yayınlanma: 2026-03-17 Okuma süresi: 10 dk

Delegate, bir nesnenin görevlerin yürütülmesini önceden tanımlanmış yöntemlere sahip bir protokol aracılığıyla başka bir nesneye devrettiği bir tasarım desenidir. iOS geliştirmede Delegate, gönderen ve alıcı arasında doğrudan bağlantı olmadan eşzamansız bildirim için kullanılan temel Cocoa Touch desenlerinden biridir. Apple Documentation (2025)'e göre, temsil yetkisi Foundation ve UIKit'te tablo olaylarını, ağ isteklerini ve konum yönetimini işlemek için kullanılır. Desen, bileşenlerin gevşek bağlanmasını ve kodun yeniden kullanılmasını sağlar.

Önemli Noktalar

  • Delegate, bir nesnenin olay işlemeyi bir protokol aracılığıyla başka bir nesneye emanet ettiği bir desendir.
  • Protocol Swift'te bir delegate'in uygulaması gereken veya uygulayabileceği yöntemler kümesini tanımlar.
  • Weak reference, retain cycle'ı önlemek için delegate özelliği için zorunludur.
  • @objc optional, protokol yöntemlerinin uygulanmasını isteğe bağlı hale getirmeye olanak tanır.
  • URLSessionDelegate, ağ isteği olaylarını işlemek için eşzamansız bir delegate'dir.

Delegate Nedir?

Delegate (temsilci), belirli bir protokolü uygulayan ve başka bir nesnenin olayları hakkında bildirimler alan bir nesnedir. Temsil yetkisi deseni, kalıtıma bir alternatiftir: yöntemleri geçersiz kılmak için bir alt sınıf oluşturmak yerine, bir nesne olay işlemeyi harici bir nesneye devreder. iOS'ta temsil yetkisi, zorunlu ve isteğe bağlı yöntemler içeren Swift protokolleri aracılığıyla uygulanır. delegate özelliği, nesneler arasında döngüsel referansları önlemek için her zaman weak var olarak bildirilir.

Delegate Protokolünü Tanımlama

Bir delegate protokolü, nesneler arasındaki etkileşim sözleşmesini tanımlar. Zorunlu yöntemler temsilci tarafından uygulanmalıdır, aksi takdirde kod derlenmez. İsteğe bağlı yöntemler @objc optional özniteliğiyle işaretlenir ve temsilcinin yalnızca ilgili olaylara yanıt vermesine olanak tanır. Yöntem adları bir kuralı takip eder: ilk parametre gönderen nesne, ikincisi olay verisidir. Örneğin, tableView(_:didSelectRowAt:), gönderenin UITableView olduğunu ve verilerin seçili satırın dizini olduğunu belirtir.

swift
// Delegate Protokolü
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 Kullanan Sınıf
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()
    }
}

Temsilciye Zayıf Referans

delegate özelliği, retain cycle'ları önlemek için weak var olarak bildirilmelidir. Referans güçlü olsaydı, temsilci ve temsil yetkisi veren nesne birbirini tutar ve ARC belleklerini serbest bırakamazdı. Delegate protokolleri, weak kullanımına izin veren AnyObject'i (yalnızca sınıflar) miras alır. Yapılar ve numaralandırmalar, değer semantiği nedeniyle temsilci olamaz. Değer türleri için bir alternatif, geri arama kapanışlarıdır (callback closures).

swift
class ViewController: DownloadManagerDelegate {
    let manager = DownloadManager()

    override func viewDidLoad() {
        super.viewDidLoad()
        manager.delegate = self // weak — retain cycle yok
        manager.startDownload(from: url)
    }

    func downloadManager(_ manager: DownloadManager, didFinishWith data: Data) {
        processData(data)
    }

    func downloadManager(_ manager: DownloadManager, didFailWith error: Error) {
        showError(error)
    }
}

iOS'ta Delegate Deseni Nasıl Çalışır?

Delegate deseni birebir temelinde çalışır: bir gönderen nesnenin belirli bir zamanda yalnızca bir delegate'i olabilir. Bir olay meydana geldiğinde, gönderen delegate'in ayarlanıp ayarlanmadığını kontrol eder ve ilgili protokol yöntemini çağırır. Doğrudan çağrılara göre avantajı, gönderenin delegate'in türünü bilmemesi, yalnızca protokole uygun olduğunu bilmesidir. Bu, SOLID'den Bağımlılığı Tersine Çevirme İlkesi'ne (DIP) uyar.

Temsilci Yaşam Döngüsü

Temsilci atama yoluyla belirlenir: someObject.delegate = self. Temsilcinin belleği serbest bırakıldığında, weak semantiği nedeniyle özellik otomatik olarak nil olur. Bir temsilci yöntemini çağırmadan önce, isteğe bağlı zincirleme yoluyla temsilci kontrol edilir: delegate?.method(). delegate nil ise, çağrı çökme olmadan yok sayılır. İsteğe bağlı protokol yöntemleri için ek bir kontrol kullanılır: delegate?.responds(to: #selector(...)), ancak Swift'te bu kontrol genellikle isteğe bağlı yöntem bildirimi yoluyla örtük olarak yapılır.

Delegate Aracılığıyla Eşzamansız Bildirim

Çok iş parçacıklı bir ortamda, delegate eşzamansız sonuç dönüşü için kullanılır. URLSession, veri alındığında, zaman aşımında veya kimlik doğrulama hatasında çağrılan yöntemlerle URLSessionDelegate sağlar. Delegate yöntemleri URLSession'ın arka plan kuyruğunda yürütülür, bu nedenle UI güncellemeleri için ana kuyruğa gönderme yapılması gerekir. Eşzamansız delegate, çağıran iş parçacığını engellemez ve diğer görevlerin devam etmesine izin verir.

swift
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 vs Callback: Yaklaşımların Karşılaştırması

Delegate ve Callback aynı sorunu — eşzamansız bildirim — ancak farklı şekillerde çözer. Delegate adlandırılmış yöntemlerle bir protokol kullanırken, Callback bağlam yakalamalı bir kapanış (closure) kullanır. Seçim, olayların sayısına, imza karmaşıklığına ve mimari tercihlere bağlıdır. Apple, birden çok olayı olan API'ler için Delegate (UITableView — 20'den fazla yöntem) ve tek seferlik tamamlamalar için Callback önerir.

Delegate Ne Zaman Kazanır

Delegate, tek bir kaynaktan birden çok farklı olayı işlerken tercih edilir. Örneğin, CLLocationManager, temsilcisine konum değişiklikleri, izin hataları, coğrafi sınır giriş/çıkışı ve hizmet durumu değişiklikleri hakkında bildirimde bulunur. Her olay, net bir ad ve türü belirtilmiş parametrelerle ayrı bir protokol yöntemidir. Delegate, davranış yapılandırması (should, will, did yöntemleri) için de kullanışlıdır.

Callback Ne Zaman Kazanır

Callback, tek bir sonucu olan tek seferlik istekler için daha basittir. URLSession.dataTask'teki Completion handler, çağrı noktasında en az üç protokol yöntemine karşı bir satır kaplar. Callback, işlevsel zincirler (map, flatMap, async/await) için de daha doğaldır. Ancak, 2-3 seviyenin üzerinde iç içe geçme ile Callback, Callback Hell'e dönüşürken, Delegate her zaman düz kalır.

iOS SDK'da Yerleşik Delegeler

iOS SDK, çeşitli alt sistemler için düzinelerce yerleşik delegate protokolü içerir. Her biri belirli bir etkileşim senaryosu için tasarlanmıştır. Apple Documentation (2025)'e göre, en çok kullanılan delegeler UITableViewDelegate, UITextFieldDelegate, CLLocationManagerDelegate, URLSessionDelegate ve UNUserNotificationCenterDelegate'dir. Bu protokoller, farklı zorunluluk seviyelerinde 3 ila 30 yöntem içerir.

UITableViewDelegate

UITableViewDelegate, tablo hücrelerinin görünümünü ve davranışını yönetir. Satır seçimini işleme, hücre yüksekliğini yapılandırma, özel üstbilgi/altbilgi görünümleri ve kaydırma eylemleri için yöntemler içerir. Tüm protokol yöntemleri isteğe bağlıdır ve yalnızca gerekli işlevselliğin uygulanmasına izin verir. Delegate olmadan tablo varsayılan ayarlarla çalışır. Tarihsel olarak, delegate UITableViewDataSource ile birleştirilmiştir.

URLSessionDelegate

URLSessionDelegate, HTTP istekleri üzerinde ayrıntılı kontrol sağlar. Sunucu yanıtı alındığında, veri geldiğinde veya indirme tamamlandığında delegate yöntemleri çağrılır. Özelleştirilmiş alt protokoller URLSessionTaskDelegate ve URLSessionDataDelegate, belirli görev türleri için temel işlevselliği genişletir. Arka plan indirmelerini, SSL sertifikalarını ve özel yönlendirme işlemeyi desteklemek için delegate gereklidir.

DelegateYöntemAmaç
UITableViewDelegate25Tablo görünümü ve etkileşimi
UITextFieldDelegate8Metin girişi ve klavye işleme
CLLocationManagerDelegate12Konum güncellemeleri ve coğrafi sınırlar
URLSessionDelegate6HTTP oturumu ve sertifika yönetimi
UNUserNotificationCenterDelegate4Ön planda push bildirimi işleme

Delegate ile Bellek Yönetimi

Bellek yönetimi, iOS'ta delegate ile çalışmanın kritik bir yönüdür. ARC (Otomatik Referans Sayma), belleği otomatik olarak yönetir, ancak yalnızca weak/unowned referanslarının doğru kullanımıyla. Kuralları ihlal etmek bellek sızıntılarına veya erken bellek serbest bırakmaya yol açar. strong olarak bildirilen bir delegate, delegate sahibi aynı zamanda temsil yetkisi veren nesneye bir referans tutuyorsa retain cycle oluşturur.

Delegate Yoluyla Retain Cycle

Retain cycle, A nesnesi (sahip) kendisini B nesnesinin delegate'i olarak ayarladığında ve B, delegate'e güçlü bir referans tuttuğunda meydana gelir. Örnek: ViewController, URLSession oluşturur, kendisini oturumun delegate'i olarak ayarlar, ancak delegateQueue belirtilmezse URLSession varsayılan olarak delegate'e güçlü bir referans tutar. Çözüm, delegate referans türü (weak veya strong) için API belgelerini her zaman kontrol etmek ve deinit'te delegate'i açıkça nil olarak ayarlamaktır.

swift
class SafeViewController: UIViewController {
    private var session: URLSession?
    private var service: NetworkService?

    override func viewDidLoad() {
        super.viewDidLoad()
        service = NetworkService()
        service?.delegate = self
    }

    deinit {
        // deinit'te delegate'i nil yap — best practice
        service?.delegate = nil
        session?.invalidateAndCancel()
    }
}

// NSObject aracılığıyla weak delegate ile 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
        )
    }
}

Çağrıdan Önce Güvenli Delegate Kontrolü

Bir delegate yöntemini çağırmadan önce, delegate'in var olduğunu (nil olmadığını) ve çağrılan yöntemi uyguladığını doğrulamanız gerekir. Zorunlu protokol yöntemleri için herhangi bir kontrol gerekmez — derleyici uygulamayı garanti eder. İsteğe bağlı yöntemler için respond(to:) veya isteğe bağlı zincirleme kullanın. Temsilcinin belleği serbest bırakılırsa, weak referans otomatik olarak nil olur ve delegate çağrısı yok sayılır. Bu, ek işlem gerektirmeyen güvenli bir davranıştır.

Delegate Uygulamasında Tipik Hatalar

Geliştiriciler, özellikle iOS öğreniminin ilk aşamalarında Delegate deseniyle çalışırken sıklıkla hata yaparlar. En yaygın olanlar şunlardır: strong delegate nedeniyle retain cycle, delegate?.method()'u çağırmayı unutmak, yanlış protokol yöntemi imzası, bir işlemi başlattıktan sonra delegate'i ayarlamak ve çoklu iş parçacığı çakışmaları. Her hatayı ve nasıl önleneceğini inceleyelim.

Weak Yerine Strong Referans

En kritik hata, delegate özelliğini weak var yerine strong var olarak bildirmektir. Bu, ne temsilcinin ne de temsil yetkisi veren nesnenin serbest bırakılamadığı bir retain cycle oluşturur. Sonuçlar: bellek sızıntıları, uygulama yavaşlaması ve gizli hatalar. Çözüm: delegate için her zaman weak var kullanın ve değer türlerinin temsilci olarak kullanılmasını önlemek için protokolün AnyObject'ten miras almasını sağlayın.

İşlem Başlattıktan Sonra Delegate Ayarlama

Eşzamansız bir yöntem çağrıldıktan sonra delegate ayarlanırsa, ilk olaylar kaybolabilir. Örnek: manager.delegate = self atamadan önce startDownload() çağırmak, indirme eşzamanlı olarak veya çok hızlı yürütülürse tamamlama geri aramasının kaybolmasına neden olur. Çözüm: eşzamansız yöntemi çağırmadan önce delegate'i ayarlayın ve protokol yorumlarında başlatma sırasını belgeleyin.

Sıkça Sorulan Sorular

Delegate neden weak olarak bildirilir?

Weak, temsilci ve temsil yetkisi veren nesne arasında bir retain cycle'ı önler. Referans güçlü olsaydı, nesneler birbirini tutar ve ARC onları serbest bırakamazdı. Weak referans, temsilcinin belleği serbest bırakıldığında otomatik olarak nil olur. Bu, Objective-C'nin ortaya çıkışından bu yana standart bir Cocoa Touch uygulamasıdır ve geriye dönük uyumluluk için Swift'te korunmuştur.

Delegate ve dataSource arasındaki fark nedir?

Delegate olayları işler ve davranışı yönetir (hücre yüksekliği, dokunmalara yanıt). DataSource görüntülenecek verileri sağlar (satır sayısı, hücreler). Temsilci “nasıl?” sorusuna yanıt verir, dataSource “ne?” sorusuna yanıt verir. iOS'ta her ikisi de protokoller aracılığıyla uygulanır, genellikle aynı denetleyicide bulunur, ancak kavramsal olarak ayrıdır.

Bir struct temsilci olarak kullanılabilir mi?

Hayır, protokol AnyObject'ten (sınıf protokolü) miras alıyorsa kullanılamaz. Weak referanslar yalnızca referans türleri (sınıflar) için kullanılabilir. Değer türleri (struct, enum) için geri arama kapanışları veya ayrı bir sarmalayıcı sınıf kullanın. Protokolü kontrol ediyorsanız, AnyObject'ten miras almaktan kaçınabilirsiniz, ancak o zaman weak yasaktır — weak temsilci ile struct temsilci arasında bilinçli bir seçim yapın.

responds(to:) yöntemi nedir ve neden gereklidir?

responds(to:), bir nesnenin belirtilen seçiciyi uygulayıp uygulamadığını kontrol eden bir NSObjectProtocol yöntemidir. Çağırmadan önce isteğe bağlı @objc protokol yöntemlerini kontrol etmek için kullanılır. Bu kontrol olmadan, uygulanmamış isteğe bağlı bir yöntemi çağırmak NSInvalidArgumentException'a yol açar. Swift'te, @objc optional içeren protokoller için kontrol, isteğe bağlı bağlama yoluyla örtük olabilir.

Delegate bir singleton mudur?

Hayır, delegate bir temsil yetkisi desenidir, singleton değildir. Singleton'un aksine, bir temsilci çalışma zamanında değiştirilebilir ve her temsil yetkisi veren nesne için tek bir örnek olarak bulunur. Bir nesne birden çok gönderen için temsilci olabilir. Singleton, tek bir sınıf örneğini garanti eden yaratımsal bir desendir ve temsil yetkisiyle ilgisi yoktur.

Özet

  • Delegate, bir nesnenin türü belirtilmiş yöntemlerle bir protokol aracılığıyla olay işlemeyi başka bir nesneye devrettiği bir desendir.
  • Weak var, retain cycle'ları ve bellek sızıntılarını önlemek için delegate özelliği için zorunludur.
  • Protocol, zorunlu ve isteğe bağlı (@objc optional) temsil yetkisi yöntemlerini tanımlar.
  • iOS SDK, 15+ yerleşik delegate protokolü içerir: UITableViewDelegate, URLSessionDelegate, CLLocationManagerDelegate.
  • Delegate, tek bir kaynaktan 3'ten fazla farklı olay olduğunda (CLLocationManager) callback'e tercih edilir.
  • Eşzamansız delegate, iş parçacığını engellemeden veri ve ilerleme almak için URLSession'da kullanılır.
  • Eşzamansız bir işlemi başlatmadan önce delegate'i ayarlayın ve güvenli bellek yönetimi için deinit'te nil yapın.

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.

Projeyi tartış

Ayrıca okuyun