Delegate : qu'est-ce que c'est, le motif de délégation et les protocoles iOS

Auteur : IT Sectr Publié le : 2026-02-17 Temps de lecture : 9 min

Delegate est un motif de conception où un objet délègue l'exécution d'une tâche à un autre objet. Sous iOS, le motif est implémenté via les protocoles Swift et @protocol Objective-C. La délégation est l'un des motifs fondamentaux de Cocoa Touch, utilisé dans UITableViewDelegate, UITextFieldDelegate et des centaines d'autres API Apple. Selon la documentation développeur Apple (2025), environ 70 % des classes système UIKit utilisent des délégués pour personnaliser le comportement sans héritage.

Points clés

  • Delegate — un motif où l'objet A délègue l'exécution d'une tâche à l'objet B via un protocole ou une interface
  • Protocole Swift définit un ensemble de méthodes que le délégué peut ou doit implémenter
  • Référence faible au délégué est obligatoire pour prévenir les cycles de rétention et les fuites mémoire
  • UITableViewDelegate — l'exemple le plus courant de délégué sous iOS avec plus de 20 méthodes optionnelles
  • Différence avec Observer : le délégué est une relation 1:1, tandis que les notifications fonctionnent sur le principe 1:N

Qu'est-ce que le motif Delegate ?

Delegate est un motif de conception comportemental qui permet à un objet de déléguer une partie de ses responsabilités à un autre objet. Contrairement à l'héritage, où une classe enfant redéfinit les méthodes parentes, le délégué utilise la composition : l'objet propriétaire conserve une référence au délégué et appelle ses méthodes à des points spécifiques.

Le délégué définit un protocole — un ensemble de méthodes que le délégué peut implémenter. Les méthodes sont divisées en obligatoires (required) et optionnelles (optional). En Swift, les méthodes optionnelles du protocole sont marquées avec le mot-clé @objc optional.

Comment fonctionne le délégué

L'objet A (propriétaire) contient une propriété delegate — une référence faible à l'objet B (délégué). Lorsqu'un événement se produit, A vérifie si B implémente la méthode de protocole correspondante et l'appelle. La référence faible est obligatoire : sans elle, le délégué ne peut pas être libéré de la mémoire car le propriétaire le retient avec une référence forte.

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

La classe DataLoader définit le protocole LoaderDelegate et appelle les méthodes du délégué aux points clés du cycle de chargement. AnyObject garantit que le protocole ne peut être implémenté que par des classes — ceci est nécessaire pour la référence faible.

Comment fonctionne Delegate en Swift ?

L'implémentation du délégué en Swift comprend trois étapes : déclarer le protocole, créer une propriété delegate faible dans le propriétaire et implémenter le protocole dans la classe déléguée. Prenons l'exemple d'un UITextField personnalisé avec validation.

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("Échec de la validation : saisie trop courte")
    }
}

LoginViewController implémente le protocole ValidatorDelegate et se désigne comme délégué de textField. À chaque modification de texte, ValidatedTextField appelle validate(_:), et si la validation échoue — validatorDidFail(_:). Le contrôleur agit comme intermédiaire entre la Vue et la logique de validation.

Delegate vs NotificationCenter vs Closure

Le choix entre délégué, notifications et closures dépend du nombre de destinataires et du couplage des composants. Chaque mécanisme résout le problème de communication entre objets, mais avec des compromis différents.

CaractéristiqueDelegateNotificationCenterClosure
Type de communication1:11:N1:1
CouplageFaible (via protocole)Très faible (clé chaîne)Moyen (capture de contexte)
Sécurité des typesComplèteAucune (Any?)Complète
Risque de cycle de rétentionNon (weak)NonOui (capture de self)
Quand utiliserCallbacks complexes avec plusieurs méthodesÉvénements intéressant plusieursClosures simples avec 1-2 callbacks

Delegate est optimal lorsque vous devez transmettre une série d'événements liés à un seul destinataire. NotificationCenter est mieux pour les notifications broadcast. Closure est pour les opérations asynchrones simples, comme les gestionnaires d'achèvement dans URLSession.

Implémentation de Delegate en Objective-C

Objective-C utilise @protocol et @optional pour déclarer les délégués. Contrairement à Swift, toutes les méthodes du protocole sont optionnelles par défaut. La principale différence est l'appel respondsToSelector: avant d'envoyer un message au délégué, car la méthode peut ne pas être implémentée.

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];
    }
    // chargement asynchrone d'image
}
@end

La principale différence en Objective-C : avant d'appeler une méthode optionnelle, une vérification respondsToSelector: est nécessaire. En Swift, les méthodes optionnelles du protocole éliminent cette vérification — l'optional chaining (?.) gère automatiquement l'absence d'implémentation.

Erreurs courantes avec les délégués

Les erreurs d'utilisation des délégués entraînent des fuites mémoire, des crashs de l'application et des bugs non évidents. Examinons les cinq problèmes les plus courants.

Référence forte au délégué

Le cycle de rétention est l'erreur la plus courante. Si la propriété delegate est déclarée comme strong, et que le délégué possède à son tour l'objet propriétaire, un cycle de rétention se forme. Les deux objets ne seront jamais libérés de la mémoire. Solution : déclarez toujours le délégué comme weak var en Swift ou @property (weak) en Objective-C.

Délégué non nul après dealloc

Si l'objet propriétaire survit au délégué et que la référence reste, l'appel de la méthode du délégué entraînera EXC_BAD_ACCESS. La référence faible résout ce problème automatiquement : après la libération du délégué, la propriété devient nil. Cependant, dans les scénarios multithread, vous devez vérifier supplémentairement le délégué sur le thread principal.

Nombre excessif de méthodes dans le protocole

Un protocole avec plus de 20 méthodes viole le principe de ségrégation des interfaces (ISP). UITableViewDelegate contient environ 30 méthodes optionnelles — c'est une exception historique. Dans vos propres protocoles, il est préférable de diviser la responsabilité en plusieurs petits protocoles, chacun avec son propre rôle.

Exemples de Delegate dans les API système iOS

Les API système Apple utilisent activement le motif Delegate. Examinons trois exemples clés d'UIKit qui apparaissent dans chaque application iOS.

APIProtocoleMéthodes clés
UITableViewUITableViewDelegatedidSelectRowAt, heightForRowAt, willDisplay
UITextFieldUITextFieldDelegateshouldChangeCharactersIn, didBeginEditing, shouldReturn
URLSessionURLSessionDelegatedidReceiveChallenge, didCompleteWithError, didBecomeInvalidWithError

Chacun de ces protocoles implémente différents aspects du comportement : UITableViewDelegate gère l'apparence et la réponse tactile, UITextFieldDelegate contrôle la saisie de texte, URLSessionDelegate traite les événements réseau. Cela démontre la flexibilité du motif : le délégué peut être adapté à tout domaine de responsabilité.

Foire aux questions

Quelle est la différence entre delegate et dataSource sous iOS ?

Delegate gère le comportement et l'apparence (hauteur de cellule, réponse tactile). DataSource fournit les données (nombre de lignes, contenu des cellules). Dans UITableViewDelegate et UITableViewDataSource — ce sont deux protocoles séparés qui divisent la responsabilité entre présentation et données.

Pourquoi delegate est-il déclaré comme weak ?

La référence faible empêche les cycles de rétention. Le propriétaire (par exemple, UITableView) ne conserve une référence au délégué qu'en weak. Si le délégué (UIViewController) possède la table, une référence forte au délégué créerait un cycle : ViewController → UITableView → Delegate (ViewController). Weak brise ce cycle.

Peut-on utiliser delegate dans SwiftUI ?

Dans SwiftUI, le motif Delegate est moins utilisé — il est remplacé par @Binding, @State et les closures. Cependant, le délégué est toujours utilisé pour l'intégration UIKit via UIViewRepresentable. Par exemple, MKMapViewDelegate et WKUIDelegate restent pertinents lors de l'encapsulation de composants UIKit dans SwiftUI.

Qu'est-ce que @objc optional dans les protocoles Swift ?

@objc optional permet de déclarer des méthodes optionnelles dans un protocole Swift. C'est un mécanisme de compatibilité avec l'environnement d'exécution Objective-C. Sans @objc, toutes les méthodes du protocole Swift sont obligatoires par défaut. Optional est utilisé dans les protocoles UIKit où le délégué ne peut implémenter que les méthodes dont il a besoin.

Combien de délégués un objet peut-il avoir ?

Un objet peut avoir un seul délégué pour chaque propriété delegate. Si vous devez notifier plusieurs objets, utilisez un délégué multicast, un tableau de délégués ou NotificationCenter. Le motif Delegate a été initialement conçu comme une relation 1:1.

Résumé

    li
  • Delegate — un motif de conception comportemental qui transfère l'exécution d'une tâche d'un objet à un autre via un protocole
  • Protocole Swift déclare un ensemble de méthodes ; les méthodes optionnelles sont marquées avec @objc optional, les méthodes obligatoires sont toujours implémentées
  • Référence faible au délégué est obligatoire pour prévenir les cycles de rétention et les fuites mémoire
  • UITableViewDelegate est l'exemple le plus connu ; ses méthodes gèrent la hauteur, la sélection et l'affichage des cellules
  • Delegate diffère de NotificationCenter par une relation 1:1 versus 1:N et une sécurité de type complète
  • Objective-C nécessite la vérification respondsToSelector: pour les méthodes optionnelles, Swift gère cela automatiquement
  • Recommandation : utilisez delegate pour les callbacks complexes avec plusieurs méthodes liées et closure pour les closures simples

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi