Delegate: wat is het, delegatiepatroon en iOS-protocollen

Auteur: IT Sectr Gepubliceerd: 2026-02-17 Leestijd: 9 min

Delegate — is een ontwerppatroon waarbij een object de uitvoering van een taak delegeert aan een ander object. In iOS wordt het patroon geïmplementeerd via Swift-protocollen en @protocol Objective-C. Delegation is een van de fundamentele patronen van Cocoa Touch, gebruikt in UITableViewDelegate, UITextFieldDelegate en honderden andere Apple API's. Volgens Apple Developer Documentation (2025) gebruikt ongeveer 70% van de systeemklassen van UIKit delegaten om gedrag aan te passen zonder overerving.

Belangrijkste punten

  • Delegate — patroon waarbij object A de uitvoering van een taak delegeert aan object B via een protocol of interface
  • Swift-protocol definieert een reeks methoden die de delegaat kan of moet implementeren
  • Weak-referentie naar de delegaat is verplicht om retain cycle en geheugenlekken te voorkomen
  • UITableViewDelegate — het meest voorkomende voorbeeld van een delegaat in iOS met 20+ optionele methoden
  • Verschil met Observer: delegaat is een 1:1-relatie, terwijl meldingen werken volgens het 1:N-principe

Wat is het Delegate-patroon?

Delegate — is een gedragsontwerppatroon waarmee een object een deel van zijn verantwoordelijkheden kan overdragen aan een ander object. In tegenstelling tot overerving, waarbij de subclass methoden van de ouder overschrijft, gebruikt de delegaat compositie: het eigenaars-object slaat een referentie naar de delegaat op en roept zijn methoden op specifieke punten aan.

De delegaat definieert een protocol — een reeks methoden die de delegaat kan implementeren. Methoden zijn onderverdeeld in verplichte (required) en optionele (optional). In Swift worden optionele protocolmethoden gemarkeerd met het sleutelwoord @objc optional.

Werkingsprincipe van de delegaat

Object A (eigenaar) bevat de eigenschap delegate — een weak-referentie naar object B (delegaat). Wanneer een gebeurtenis plaatsvindt, controleert A of B de bijbehorende protocolmethode implementeert en roept deze aan. Weak-referentie is verplicht: zonder deze kan de delegaat niet uit het geheugen worden bevrijd, omdat de eigenaar hem met een strong-referentie vasthoudt.

Swift
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)
        // asynchrone load
    }
}

De klasse DataLoader definieert het protocol LoaderDelegate en roept de methoden van de delegaat aan op belangrijke punten in de laadcyclus. AnyObject garandeert dat het protocol alleen door klassen kan worden geïmplementeerd — dit is noodzakelijk voor de weak-referentie.

Hoe werkt Delegate in Swift?

Implementatie van de delegaat in Swift omvat drie stappen: het declareren van het protocol, het creëren van de weak delegate-eigenschap in de eigenaar en het implementeren van het protocol in de delegatenklasse. Laten we het bekijken aan de hand van een aangepaste UITextField met validatie.

Swift
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("Validatie mislukt: invoer te kort")
    }
}

LoginViewController implementeert het protocol ValidatorDelegate en stelt zichzelf aan als delegaat van textField. Bij elke tekstwijziging roept ValidatedTextField validate(_:) aan, en als de validatie mislukt — validatorDidFail(_:). Controller fungeert als tussenpersoon tussen de View en de validatielogica.

Delegate vs NotificationCenter vs Closure

De keuze tussen delegaten, meldingen en closures hangt af van het aantal ontvangers en de mate van koppeling van componenten. Elk mechanisme lost het probleem van communicatie tussen objecten op, maar met verschillende afwegingen.

KenmerkDelegateNotificationCenterClosure
Type verbinding1:11:N1:1
KoppelingZwak (via protocol)Zeer zwak (string-sleutel)Gemiddeld (context vastleggen)
TypeveiligheidVolledigAfwezig (Any?)Volledig
Retain cycle risicoNee (weak)NeeJa (self vastleggen)
Wanneer toepassenComplexe callbacks met meerdere methodenGebeurtenissen die velen interesserenEenvoudige closures met 1-2 callbacks

Delegate is optimaal wanneer een reeks gerelateerde gebeurtenissen aan één ontvanger moet worden doorgegeven. NotificationCenter is beter voor broadcast-meldingen. Closure — voor eenvoudige asynchrone bewerkingen, zoals een completion handler in URLSession.

Implementatie van Delegate in Objective-C

Objective-C gebruikt @protocol en @optional voor het declareren van delegaten. In tegenstelling tot Swift zijn alle methoden van het protocol standaard optioneel. Het belangrijkste verschil is de aanroep van respondsToSelector: voordat een bericht naar de delegaat wordt gestuurd, omdat de methode mogelijk niet is geïmplementeerd.

Objective-C
@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];
    }
    // asynchrone afbeelding laden
}
@end

Het belangrijkste verschil in Objective-C: vóór het aanroepen van een optionele methode is controle met respondsToSelector: vereist. In Swift elimineren optionele protocolmethoden deze controle — optional chaining (?.) handelt automatisch het geval van ontbrekende implementatie af.

Typische fouten bij het werken met delegaten

Fouten bij het gebruik van delegaten leiden tot geheugenlekken, crashes van de app en onduidelijke bugs. Laten we de vijf meest voorkomende problemen bekijken.

Strong-referentie naar de delegaat

Retain cycle — de meest voorkomende fout. Als de eigenschap delegate is gedeclareerd als strong en de delegaat op zijn beurt het eigenaars-object bezit, ontstaat er een retentiecyclus. Beide objecten worden nooit uit het geheugen bevrijd. Oplossing: declareer de delegaat altijd als weak var in Swift of @property (weak) in Objective-C.

Delegaat niet gereset na dealloc

Als het eigenaars-object de delegaat overleeft en de referentie blijft bestaan, leidt het aanroepen van de delegatenmethode tot EXC_BAD_ACCESS. Weak-referentie lost dit probleem automatisch op: na het vrijgeven van de delegaat wordt de eigenschap nil. In multithreading-scenario's is het echter raadzaam om de delegaat ook in de hoofdthread te controleren.

Overmatig aantal methoden in het protocol

Een protocol met meer dan 20 methoden schendt het principe van interfacescheiding (ISP). UITableViewDelegate bevat ongeveer 30 optionele methoden — dit is een historische uitzondering. In eigen protocollen is het beter om de verantwoordelijkheid te verdelen over meerdere kleine protocollen, elk met zijn eigen rol.

Voorbeelden van Delegate in systeem-API's van iOS

Systeem-API's van Apple gebruiken actief het Delegate-patroon. Laten we drie belangrijke voorbeelden uit UIKit bekijken die in elke iOS-app voorkomen.

APIProtocolBelangrijkste methoden
UITableViewUITableViewDelegatedidSelectRowAt, heightForRowAt, willDisplay
UITextFieldUITextFieldDelegateshouldChangeCharactersIn, didBeginEditing, shouldReturn
URLSessionURLSessionDelegatedidReceiveChallenge, didCompleteWithError, didBecomeInvalidWithError

Elk van deze protocollen implementeert verschillende aspecten van gedrag: UITableViewDelegate beheert het uiterlijk en de reactie op aanrakingen, UITextFieldDelegate controleert de tekstinvoer, URLSessionDelegate verwerkt netwerkgebeurtenissen. Dit toont de flexibiliteit van het patroon: de delegaat kan worden aangepast aan elk verantwoordelijkheidsgebied.

Veelgestelde vragen

Wat is het verschil tussen delegate en dataSource in iOS?

Delegate beheert het gedrag en uiterlijk (celhoogte, reactie op aanraking). DataSource levert gegevens (aantal rijen, celinhoud). In UITableViewDelegate en UITableViewDataSource zijn dit twee afzonderlijke protocollen die de verantwoordelijkheid voor presentatie en gegevens verdelen.

Waarom wordt delegate gedeclareerd als weak?

Weak-referentie voorkomt retain cycle. De eigenaar (bijv. UITableView) houdt de referentie naar de delegaat alleen als weak vast. Als de delegaat (UIViewController) de tabel bezit, zou een strong-referentie naar de delegaat een cyclus creëren: ViewController → UITableView → Delegate (ViewController). Weak verbreekt deze cyclus.

Kan delegate worden gebruikt in SwiftUI?

In SwiftUI wordt het Delegate-patroon minder vaak gebruikt — het wordt vervangen door @Binding, @State en closures. Echter, delegate wordt nog steeds gebruikt voor UIKit-integratie via UIViewRepresentable. Bijvoorbeeld MKMapViewDelegate en WKUIDelegate blijven relevant bij het inpakken van UIKit-componenten in SwiftUI.

Wat is @objc optional in Swift-protocollen?

@objc optional maakt het mogelijk om optionele methoden in een Swift-protocol te declareren. Dit is een compatibiliteitsmechanisme met Objective-C runtime. Zonder @objc zijn alle methoden van een Swift-protocol standaard verplicht. Optional wordt gebruikt in UIKit-protocollen, waar de delegaat alleen de methoden kan implementeren die hij nodig heeft.

Hoeveel delegaten kan één object hebben?

Eén object kan slechts één delegaat hebben voor elke delegate-eigenschap. Als meerdere objecten moeten worden geïnformeerd, gebruik dan multicast delegate, een array van delegaten of NotificationCenter. Het Delegate-patroon is oorspronkelijk ontworpen als een 1:1-relatie.

Samenvatting

  • Delegate — een gedragsontwerppatroon dat de uitvoering van een taak van het ene object naar het andere overdraagt via een protocol
  • Swift-protocol declareert een reeks methoden; optionele methoden worden gemarkeerd met @objc optional, verplichte worden altijd geïmplementeerd
  • Weak-referentie naar de delegaat is verplicht om retain cycle en geheugenlekken te voorkomen
  • UITableViewDelegate — het bekendste voorbeeld; zijn methoden beheren de hoogte, selectie en weergave van cellen
  • Delegate verschilt van NotificationCenter door de 1:1-relatie versus 1:N en volledige typeveiligheid
  • Objective-C vereist controle van respondsToSelector: voor optionele methoden, Swift handelt dit automatisch af
  • Aanbeveling: gebruik delegate voor complexe callbacks met meerdere gerelateerde methoden en closure voor eenvoudige afsluitingen

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