Références faibles aux protocoles en Swift sans @objc : guide complet

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Comment créer une référence faible à un protocole en Swift pur (sans @objc) ? Guide complet avec exemples

\n\n

Imaginez : vous écrivez une application en Swift, vous utilisez le pattern Delegate, et soudain — boum ! — vos objets ne sont pas détruits, la mémoire augmente, et l'application commence à ralentir. Cela vous dit quelque chose ? Vous avez très probablement rencontré un retain cycle (cycle de références fortes). Un problème classique où le délégué maintient une référence forte sur le propriétaire, et le propriétaire sur le délégué. La solution qui vient à l'esprit en premier est de rendre la référence au protocole faible (weak). Mais là, Swift nous réserve une surprise : vous ne pouvez pas simplement déclarer weak var delegate: MyProtocol si le protocole n'est pas marqué @objc. Le compilateur générera une erreur. Pourquoi ? Et surtout, comment contourner cela ?

\n\n

Dans cet article, nous allons voir comment créer une référence faible à un protocole (weak protocol reference) en Swift pur sans @objc. Vous apprendrez pourquoi c'est un problème, quelles sont les solutions, et comment écrire un code élégant et sûr, sans fuites mémoire. C'est parti !

\n\n

Pourquoi la référence faible à un protocole (weak protocol reference) ne fonctionne-t-elle pas « nativement » ?

\n\n

Rappelons comment fonctionne weak en Swift. Une référence faible (weak) ne peut exister que pour les reference types (les classes). Pourquoi ? Parce que seuls les objets de classes ont une gestion de la mémoire via ARC (Automatic Reference Counting). Les structures (struct) et les énumérations (enum) sont des value types, elles sont copiées, et la notion de « référence faible » n'a pas de sens pour elles.

\n\n

Lorsque vous écrivez :

\n
weak var delegate: MyProtocol?
\n

Le compilateur ne sait pas si MyProtocol sera implémenté par une classe, une structure ou une énumération. Et si c'était une structure ? Alors weak ne peut pas être appliqué. D'où l'erreur : « 'weak' may only be applied to class and class-bound protocol types ».

\n\n

Avant (en Objective-C), tous les protocoles pouvaient par défaut être implémentés uniquement par des classes, donc weak fonctionnait. En Swift pur, les protocoles sont universels — c'est formidable, mais cela ajoute de la complexité.

\n\n

Solution n°1 : protocole réservé aux classes (class-bound protocol)

\n\n

La méthode la plus simple et la plus courante est d'indiquer explicitement que le protocole ne peut être implémenté que par des classes. Pour cela, on utilise le mot-clé AnyObject (ou l'ancien class) dans la déclaration du protocole.

\n\n

Exemple :

\n
protocol MyDelegate: AnyObject {\n    func didSomething()\n}\n\nclass ViewController {\n    weak var delegate: MyDelegate?\n\n    func doSomething() {\n        delegate?.didSomething()\n    }\n}\n\nclass SomeClass: MyDelegate {\n    func didSomething() {\n        print("Délégué activé !")\n    }\n}\n\n// Utilisation\nlet vc = ViewController()\nlet some = SomeClass()\nvc.delegate = some\nvc.doSomething() // Affiche : "Délégué activé !"
\n\n

Tout fonctionne. MyDelegate peut désormais être implémenté uniquement par une classe (class), et weak est légal. C'est l'approche recommandée par Apple pour les délégués.

\n\n

Pourquoi est-ce bien ?

\n
    \n
  • Simplicité et lisibilité.
  • \n
  • Support complet d'ARC.
  • \n
  • Pas besoin de @objc.
  • \n
\n\n

Inconvénients ?

\n
    \n
  • Vous perdez la possibilité d'implémenter le protocole avec une structure. Mais pour les délégués, ce n'est généralement pas nécessaire.
  • \n
\n\n

Solution n°2 : Utilisation d'un wrapper générique (pour les cas exotiques)

\n\n

Et si vous devez absolument permettre au protocole d'être implémenté à la fois par des classes et des structures, tout en voulant une référence faible ? Cela arrive rarement, mais c'est possible. Par exemple, si vous écrivez une bibliothèque où l'utilisateur peut passer une classe ou une structure. Dans ce cas, une enveloppe (wrapper) vient à la rescousse.

\n\n

L'idée : créer une structure qui stocke une référence faible sur l'objet implémentant le protocole. Pour les classes — we

Blogs

Book Recommendations