Delegate: wat is het, het delegatiepatroon en hoe het werkt op iOS

Auteur: IT Sectr Gepubliceerd: 2026-03-17 Leestijd: 10 min

Delegate — is een ontwerppatroon waarbij een object de uitvoering van taken delegeert aan een ander object via een protocol met vooraf gedefinieerde methoden. In iOS-ontwikkeling is Delegate een van de fundamentele patronen van Cocoa Touch, gebruikt voor asynchrone meldingen zonder directe verbinding tussen verzender en ontvanger. Volgens Apple Documentation (2025) wordt delegatie toegepast in Foundation en UIKit voor de verwerking van tabelgebeurtenissen, netwerkverzoeken en locatiebeheer. Het patroon zorgt voor losse koppeling van componenten en hergebruik van code.

Belangrijkste punten

  • Delegate — patroon waarbij het object de verwerking van gebeurtenissen aan een ander object toevertrouwt via een protocol.
  • Protocol in Swift definieert de set methoden die de delegate moet of kan implementeren.
  • Weak reference is verplicht voor de eigenschap delegate om retain cycle te voorkomen.
  • @objc optional maakt het mogelijk om protocolmethoden optioneel te maken voor implementatie.
  • URLSessionDelegate — asynchrone delegate voor de verwerking van netwerkverzoekgebeurtenissen.

Wat is Delegate?

Delegate (delegaat) — is een object dat een specifiek protocol implementeert en meldingen ontvangt over gebeurtenissen van een ander object. Het Delegation-patroon is een alternatief voor overerving: in plaats van een subklasse te maken voor het overschrijven van methoden, delegeert het object de verwerking van gebeurtenissen aan een extern object. In iOS is delegation geïmplementeerd via Swift-protocollen met verplichte en optionele methoden. De eigenschap delegate wordt altijd gedeclareerd als weak var om cyclische verwijzingen tussen objecten te voorkomen.

Definiëren van het Delegate-protocol

Het delegate-protocol definieert het interactiecontract tussen objecten. Verplichte methoden moeten door de delegaat worden geïmplementeerd, anders compileert de code niet. Optionele methoden worden gemarkeerd met het attribuut @objc optional en stellen de delegaat in staat om alleen op de benodigde gebeurtenissen te reageren. Methodenamen volgen de conventie: eerste parameter — het verzendende object, tweede — de gebeurtenisgegevens. Bijvoorbeeld, tableView(_:didSelectRowAt:) geeft aan dat de verzender UITableView is en de gegevens de index van de geselecteerde rij.

swift
// Delegate Protocol
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)
}

// Klasse die Delegate gebruikt
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()
    }
}

Zwakke verwijzing naar delegate

De eigenschap delegate moet worden gedeclareerd als weak var (zwakke pointer) om retain cycle te voorkomen. Als de verwijzing sterk was, zouden de delegaat en het delegerende object elkaar vasthouden en zou ARC hun geheugen niet kunnen vrijgeven. Delegate-protocollen erven AnyObject (alleen voor klassen), wat het gebruik van weak mogelijk maakt. Structuren en enum kunnen geen delegaten zijn vanwege de waardesemantiek. Alternatief voor value types — callback closures.

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

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

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

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

Hoe werkt het Delegate-patroon in iOS?

Het Delegate-patroon werkt op het principe van “een-op-een”: een verzendend object kan op een bepaald moment slechts één delegaat hebben. Wanneer een gebeurtenis plaatsvindt, controleert de verzender of delegate is ingesteld en roept de overeenkomstige methode van het protocol aan. Voordeel ten opzichte van directe aanroep — de verzender kent het type van de delegaat niet, alleen dat deze overeenkomt met het protocol. Dit is in overeenstemming met het principe van inversie van afhankelijkheden (DIP) uit SOLID.

Levenscyclus van de delegaat

De delegaat wordt ingesteld via toewijzing: someObject.delegate = self. Bij deallocatie van de delegaat wordt de eigenschap automatisch nil vanwege de weak-semantiek. Vóór het aanroepen van de delegate-methode wordt gecontroleerd via optional chaining: delegate?.method(). Als delegate nil is — wordt de aanroep genegeerd zonder crash. Voor optionele protocolmethoden wordt een aanvullende controle gebruikt: delegate?.responds(to: #selector(...)), hoewel in Swift deze controle meestal impliciet is via de declaratie van optionele methoden.

Asynchrone melding via Delegate

In een multi-threaded omgeving wordt delegate gebruikt voor asynchrone terugkeer van resultaten. URLSession biedt URLSessionDelegate met methoden die worden aangeroepen bij het ontvangen van gegevens, timeout of authenticatiefout. Delegate-methoden worden uitgevoerd in de achtergrondwachtrij van URLSession, dus is dispatchen naar de main queue vereist voor UI-updates. Asynchrone delegate blokkeert de aanroepende thread niet, waardoor andere taken kunnen worden voortgezet.

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: vergelijking van benaderingen

Delegate en Callback lossen dezelfde taak op — asynchrone melding — maar op verschillende manieren. Delegate gebruikt een protocol met benoemde methoden, callback — een closure met contextvastlegging. De keuze hangt af van het aantal gebeurtenissen, de complexiteit van handtekeningen en architecturale voorkeuren. Apple beveelt delegate aan voor API's met meerdere gebeurtenissen (UITableView — 20+ methoden) en callback voor eenmalige voltooiingen.

Wanneer Delegate wint

Delegate heeft de voorkeur wanneer meerdere verschillende gebeurtenissen van één bron moeten worden verwerkt. Bijvoorbeeld, CLLocationManager stelt de delegaat op de hoogte van locatieverandering, toestemmingsfouten, betreden/verlaten van geografische zones en verandering van servicestatus. Elke gebeurtenis is een aparte protocolmethode met een duidelijke naam en getypeerde parameters. Delegate is ook handig voor het configureren van gedrag (should, will, did methoden).

Wanneer Callback wint

Callback is eenvoudiger voor eenmalige verzoeken met één resultaat. Completion handler in URLSession.dataTask beslaat één regel op het aanroepspunt tegenover ten minste drie protocolmethoden. Callback is ook natuurlijker voor functionele ketens (map, flatMap, async/await). Bij nesting van meer dan 2-3 niveaus verandert callback echter in Callback Hell, terwijl delegate altijd plat blijft.

Ingebouwde Delegates in iOS SDK

iOS SDK bevat tientallen ingebouwde delegate-protocollen voor verschillende subsystemen. Elk daarvan is ontworpen voor een specifiek interactiescenario. Volgens Apple Documentation (2025) zijn de meest gebruikte delegates UITableViewDelegate, UITextFieldDelegate, CLLocationManagerDelegate, URLSessionDelegate en UNUserNotificationCenterDelegate. Deze protocollen bevatten 3 tot 30 methoden met verschillende mate van verplichting.

UITableViewDelegate

UITableViewDelegate beheert het uiterlijk en gedrag van tabelcellen. Het bevat methoden voor het verwerken van rijselectie, het instellen van celhoogte, aangepaste header/footer-weergaven en swipe-acties. Alle methoden van het protocol zijn optioneel, waardoor alleen de benodigde functionaliteit kan worden geïmplementeerd. Bij afwezigheid van een delegaat werkt de tabel met standaardinstellingen. Historisch gezien werd delegate gecombineerd met UITableViewDataSource.

URLSessionDelegate

URLSessionDelegate biedt gedetailleerde controle over HTTP-verzoeken. De methoden van de delegaat worden aangeroepen bij ontvangst van serverantwoord, gegevens, voltooiing van download. Gespecialiseerde subprotocollen URLSessionTaskDelegate en URLSessionDataDelegate breiden de basisfunctionaliteit uit voor specifieke taaktypen. Delegate is vereist voor ondersteuning van achtergronddownloads, SSL-certificaten en aangepaste verwerking van omleidingen.

DelegateMethodenDoel
UITableViewDelegate25Uiterlijk en interactie met tabel
UITextFieldDelegate8Verwerking van tekstinvoer en toetsenbord
CLLocationManagerDelegate12Locatie-updates en geografische zones
URLSessionDelegate6Beheer van HTTP-sessie en certificaten
UNUserNotificationCenterDelegate4Verwerking van pushmeldingen op de voorgrond

Geheugenbeheer bij het werken met Delegate

Geheugenbeheer is een kritisch aspect van het werken met delegate in iOS. ARC (Automatic Reference Counting) beheert automatisch het geheugen, maar alleen bij correct gebruik van weak/unowned verwijzingen. Overtreding van de regels leidt tot geheugenlekken of vroegtijdige deallocatie. Delegate gedeclareerd als strong creëert een retain cycle als de eigenaar van de delegaat ook een verwijzing naar het delegerende object bewaart.

Retain cycle via Delegate

Retain cycle ontstaat wanneer object A (eigenaar) zichzelf als delegaat van object B instelt en B een sterke verwijzing naar delegate bewaart. Voorbeeld: ViewController maakt URLSession, stelt self in als delegaat van de sessie, maar URLSession standaard bewaart een sterke verwijzing naar delegate als er geen delegateQueue is opgegeven. Oplossing — controleer altijd de API-documentatie voor het type verwijzing naar delegate (weak of strong) en stel delegate expliciet in op nil in deinit.

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

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

    deinit {
        // Delegate nulstellen in deinit — best practice
        service?.delegate = nil
        session?.invalidateAndCancel()
    }
}

// URLSession met weak delegate via 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
        )
    }
}

Veilige controle van delegate vóór aanroep

Voordat de methode van de delegaat wordt aangeroepen, moet worden gecontroleerd of de delegaat bestaat (niet nil) en de aangeroepen methode implementeert. Voor verplichte protocolmethoden is controle niet nodig — de compiler garandeert implementatie. Voor optionele methoden gebruik respond(to:) of optional chaining. Als de delegaat is gedealloceerd, wordt de weak-verwijzing automatisch nil en wordt de delegaataanroep genegeerd. Dit is veilig gedrag dat geen verdere verwerking vereist.

Typische fouten bij het implementeren van Delegate

Ontwikkelaars maken vaak fouten bij het werken met het Delegate-patroon, vooral in de beginfase van het leren van iOS. Meest voorkomend: retain cycle door strong delegate, vergeten aanroepen van delegate?.method(), onjuiste handtekening van protocolmethoden, instellen van delegate na start van de operatie en multi-threaded botsingen. Laten we elke fout en manieren om deze te voorkomen bekijken.

Strong reference in plaats van weak

De meest kritieke fout — declareren van de eigenschap delegate als strong var in plaats van weak var. Dit creëert een retain cycle waarbij noch de delegaat, noch het delegerende object kunnen worden vrijgegeven. Gevolgen: geheugenlek, vertraging van de applicatie en verborgen bugs. Oplossing: gebruik altijd weak var voor delegate en laat het protocol overerven van AnyObject om het gebruik van value types als delegaat uit te sluiten.

Instellen van delegate na start van de operatie

Als delegate wordt ingesteld na het aanroepen van een asynchrone methode, kunnen eerste gebeurtenissen verloren gaan. Voorbeeld: aanroepen van startDownload() vóór toewijzing van manager.delegate = self leidt tot verlies van de voltooiings-callback als de download synchroon of zeer snel wordt uitgevoerd. Oplossing: stel delegate in vóór het aanroepen van de asynchrone methode en documenteer de initialisatievolgorde in de opmerkingen bij het protocol.

Veelgestelde vragen

Waarom wordt delegate gedeclareerd als weak?

Weak voorkomt retain cycle tussen de delegaat en het delegerende object. Als de verwijzing strong was, zouden objecten elkaar vasthouden en zou ARC ze niet kunnen vrijgeven. Weak-verwijzing wordt automatisch nil bij deallocatie van de delegaat. Dit is standaardpraktijk van Cocoa Touch sinds het begin van Objective-C en is behouden in Swift voor achterwaartse compatibiliteit.

Wat is het verschil tussen delegate en dataSource?

Delegate verwerkt gebeurtenissen en beheert gedrag (celhoogte, reactie op klikken). DataSource levert gegevens voor weergave (aantal rijen, cellen). Delegate beantwoordt de vraag “hoe?”, dataSource — de vraag “wat?”. In iOS worden beide geïmplementeerd via protocollen, vaak in dezelfde controller, maar conceptueel gescheiden.

Kan struct worden gebruikt als delegate?

Nee, als het protocol AnyObject (klassenprotocol) overerft. Weak-verwijzingen zijn alleen beschikbaar voor reference types (klassen). Voor value types (struct, enum) gebruikt u callback closures of een aparte wrapper-klasse. Als u het protocol beheert, kunt u AnyObject niet overerven, maar dan is weak verboden — kies bewust tussen weak-delegate en struct-delegaat.

Wat is de methode responds(to:) en waar dient deze voor?

responds(to:) — is een methode van NSObjectProtocol die controleert of het object de opgegeven selector implementeert. Wordt gebruikt voor het controleren van optionele @objc-protocolmethoden vóór aanroep. Zonder deze controle leidt het aanroepen van een niet-geïmplementeerde optionele methode tot NSInvalidArgumentException. In Swift voor protocollen met @objc optional kan de controle impliciet zijn via optional binding.

Is Delegate een singleton?

Nee, delegate is een delegatiepatroon, geen singleton. In tegenstelling tot een singleton kan de delegaat tijdens runtime worden vervangen en bestaat er één instantie voor elk delegerend object. Één object kan delegaat zijn voor meerdere verzenders. Singleton is een creatiepatroon dat een enkele instantie van een klasse garandeert en heeft niets te maken met delegatie.

Samenvatting

  • Delegate — patroon waarbij het object de verwerking van gebeurtenissen delegeert aan een ander object via een protocol met getypeerde methoden.
  • Weak var is verplicht voor de eigenschap delegate om retain cycle en geheugenlekken te voorkomen.
  • Protocol definieert de verplichte en optionele (@objc optional) delegatiemethoden.
  • iOS SDK bevat 15+ ingebouwde delegate-protocollen: UITableViewDelegate, URLSessionDelegate, CLLocationManagerDelegate.
  • Delegate heeft de voorkeur boven callback bij 3+ verschillende gebeurtenissen van één bron (CLLocationManager).
  • Asynchrone delegate wordt gebruikt in URLSession voor het verkrijgen van gegevens en voortgang zonder threadblokkering.
  • Stel delegate in vóór het starten van een asynchrone operatie en zet hem op nil in deinit voor veilig geheugenbeheer.

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook