Unowned Reference (référence non possédée) est une référence non propriétaire en Swift qui n'augmente pas le retain count de l'objet et, contrairement à weak, n'est pas définie à nil après la libération de l'objet. Selon Apple Swift Language Guide, 2026, unowned est utilisé lorsqu'il est garanti que l'objet vit au moins aussi longtemps que l'objet qui le référence. Contrairement à Weak Reference, unowned ne nécessite pas d'unwrap « c'est un type non optionnel, ce qui rend le code plus propre mais place la responsabilité sur le développeur de garantir la durée de vie.
Points Clés
Unowned Reference est une référence non propriétaire à un objet dans ARC qui n'augmente pas son retain count. Contrairement à weak, une référence unowned n'est pas remise à zéro après la désallocation de l'objet : elle continue à pointer vers de la mémoire déjà libérée. Accéder à une telle référence provoque un crash au moment de l'exécution avec EXC_BAD_ACCESS.
Le terme « non possédée » reflète la sémantique : l'objet existe, mais personne n'est responsable de sa durée de vie. Le développeur déclare explicitement : « je garantis que cet objet sera vivant tant que je le référence. » Le compilateur ne vérifie pas cette garantie « c'est un contrat au niveau du développeur.
Selon Swift.org Documentation, 2026, les références unowned sont préférées à weak dans les scénarios avec durée de vie garantie car elles : ne nécessitent pas de type optionnel (code plus propre), ne nécessitent pas d'unwrap (moins de force-unwrap ou guard let), et n'ont pas de surcharge de maintenance d'une table weak de remise à zéro. Cependant, toute violation du contrat entraîne un crash.
En Swift, les références unowned sont déclarées avec le mot-clé unowned avant let ou var. Contrairement à weak, unowned peut être à la fois let et var, et ne nécessite pas de type optionnel. Cette propriété rend unowned pratique pour les références qui ne peuvent pas être nil par logique de domaine.
class Country {
let name: String
var capital: City! // sera défini après l'initialisation
init(name: String) { self.name = name }
}
class City {
let name: String
unowned let country: Country // ✅ unowned let — garantie de vie
init(name: String, country: Country) {
self.name = name
self.country = country
}
}
// Utilisation
let france = Country(name: "France")
let paris = City(name: "Paris", country: france)
france.capital = paris
// ✅ Country → City (strong), City → Country (unowned) — pas de retain cycle
Dans cet exemple, City unowned let country « une ville ne peut pas exister sans un pays. Si le pays disparaît, la ville (et la référence) perdent leur sens. Sémantiquement, c'est un cas idéal pour unowned : la garantie de durée de vie existe, l'optionnel n'est pas nécessaire, le retain cycle ne se produit pas.
unowned var est autorisé mais moins courant. Il est utilisé lorsque la référence peut être remplacée (par exemple, réattacher un enfant à un parent différent). Lors de la réaffectation, la désallocation de l'ancien objet est la responsabilité du propriétaire externe.
Dans Swift 5.0+, le support de l'optionnel unowned (unowned let x: Type?) a été introduit. C'est un compromis : unowned garantit que si la référence n'est pas nil, l'objet est vivant. Le comportement lors de la désallocation est un crash, comme avec unowned normal.
Le choix entre unowned et weak est l'une des décisions fréquentes lors de la conception d'architecture Swift. Examinons les critères et recommandations pour chaque cas.
| Critère | Weak | Unowned |
|---|---|---|
| Optionnel | Oui (Type?) | Non (Type) |
| Remise à zéro à la désallocation | Auto à nil | Non (risque de pointeur pendant) |
| Type (let/var) | Var uniquement | let ou var |
| Performance | Surcharge de la table weak | Minimale (pointeur simple) |
| Sécurité | Sûr (nil vérifié) | Risque d'EXC_BAD_ACCESS |
| Garantie de durée de vie | Non requise | Garantie explicite requise |
Utilisez weak s'il y a le moindre doute sur la durée de vie de l'objet. Weak est sûr, clair et ne nécessite pas de preuve. Utilisez unowned seulement lorsque vous pouvez exclure tous les scénarios dans lesquels l'objet pourrait être désalloué plus tôt. Cas typiques : un enfant qui n'existe pas sans un parent ; une closure qui s'exécute de manière synchrone ; l'accès à un objet dans son initialiseur.
Selon Airbnb Swift Style Guide, 2025, dans les grandes bases de code, il est recommandé d'utiliser weak par défaut et unowned uniquement avec un commentaire explicite expliquant la garantie de durée de vie. Cela réduit le risque de crashes non évidents lors du refactoring.
Les closures sont le deuxième cas d'utilisation le plus fréquent pour unowned après les relations parent-enfant. La liste de capture [unowned self] est utilisée lorsqu'il est garanti que self survit à la closure. Examinons les scénarios corrects et incorrects.
Closures synchrones « sorted, filter, map. Elles s'exécutent immédiatement dans le thread actuel, self est définitivement vivant. Une liste de capture avec unowned est acceptable ici et donne un code plus propre.
class DataProcessor {
var items: [Int] = [3, 1, 4, 1, 5]
func processSorted() {
// ✅ unowned self — sorted s'exécute de manière synchrone, self est garanti vivant
let sorted = items.sorted { [unowned self] a, b in
return self.customCompare(a, b)
}
}
func customCompare(_ a: Int, _ b: Int) -> Bool { return a < b }
}
Closures asynchrones « avec délais, requêtes réseau, animations. Self peut être désalloué entre la planification de la closure et son exécution. Ici, unowned self mène à un crash. Utilisez [weak self].
class NetworkLoader {
func loadData() {
// ❌ DANGEREUX : unowned self dans une closure asynchrone
URLSession.shared.dataTask(with: url) { [unowned self] data, _, _ in
self.handleResponse(data) // CRASH si self est libéré
}.resume()
}
func handleResponse(_ data: Data?) { }
// ✅ CORRECT : weak self + guard
func loadDataSafe() {
URLSession.shared.dataTask(with: url) { [weak self] data, _, _ in
guard let self else { return }
self.handleResponse(data)
}.resume()
}
}
Retenez la règle : unowned self « uniquement pour les closures synchrones qui s'exécutent immédiatement. Pour les closures asynchrones, utilisez toujours weak self + guard let. Exception : si vous conservez explicitement une référence à l'objet jusqu'à ce que la closure se termine (par exemple, en gardant une référence forte dans une autre variable).
Unowned est un outil puissant mais dangereux. Examinons des scénarios réels où unowned peut entraîner des crashes et des méthodes pour minimiser le risque.
Le risque principal de unowned est un changement dans la logique métier qui invalide la garantie de durée de vie. Un développeur refactorise le code : change la propriété, introduit une désallocation différée, ajoute du caching « et la référence unowned devient une bombe à retardement. Le compilateur ne prévient pas « seulement un crash sur l'appareil de l'utilisateur.
Recommandation : utilisez unowned seulement lorsque la garantie de durée de vie est évidente et documentée. Ajoutez un commentaire à chaque unowned : pourquoi cette référence est sûre et dans quelles conditions elle pourrait être violée.
UIKit est une zone à haut risque pour unowned. Un ViewController peut être désalloué à tout moment pendant la navigation (pop, dismiss), le déchargement mémoire ou les changements d'orientation. Si vous passez un ViewController à une closure avec unowned self, self peut être nil au retour de l'arrière-plan ou à la fin d'une animation.
Pour réduire le risque lors de l'utilisation de unowned, suivez ces règles :
// Exemple : référence unowned documentée avec justification explicite
class InvoiceLineItem {
let productName: String
let price: Decimal
// unowned Invoice — InvoiceLineItem ne peut pas exister sans Invoice.
// Invoice crée Item et le supprime lors de sa suppression.
// Garantie : Invoice vit au moins aussi longtemps que Item.
unowned let invoice: Invoice
init(productName: String, price: Decimal, invoice: Invoice) {
self.productName = productName
self.price = price
self.invoice = invoice
}
}
// C'est une garantie forte : Invoice supprime tous les Items dans deinit.
// violer la garantie = un bug dans la logique métier qui doit être corrigé.
Documenter les garanties est une norme professionnelle. Dans les grands projets (Airbnb, Uber), la revue de code exige une justification pour chaque unowned. Si la garantie n'est pas évidente, utilisez weak. Un commentaire sur unowned aide les développeurs futurs à comprendre pourquoi weak n'a pas été utilisé ici et quelles conditions pourraient briser la garantie.
Foire aux questions
Crash au moment de l'exécution avec EXC_BAD_ACCESS. Swift ne vérifie pas la validité d'une référence unowned lors de l'accès « c'est simplement un pointeur « brut ». Si l'objet est libéré, la mémoire est écrasée et y accéder se termine fatalement. C'est une exception non rattrapable (pas try-catch).
Oui, si le protocole hérite de AnyObject. Unowned fonctionne avec tous les types de référence : classes, protocoles AnyObject, objets Objective-C. Les types de valeur (struct, enum) ne supportent pas unowned car ils ne participent pas à ARC.
Lorsque la garantie de durée de vie est absolue et évidente « unowned est plus sûr d'un point de vue conception : il ne nécessite pas d'unwrap, ne peut pas être nil et ne masque pas les erreurs. Si un objet ne peut pas exister sans parent, unowned en fait un contrat explicite, tandis que weak brouille la garantie.
Oui : unowned est plus rapide car il ne nécessite pas d'accès à la table weak au moment de l'exécution pour la remise à zéro. Dans la plupart des applications, la différence est imperceptible, mais dans des scénarios à forte charge avec des millions d'accès, unowned peut être 10 à 20% plus rapide en lecture.
Le refactoring est le principal danger pour unowned. Modifier la durée de vie de l'objet (caching, opérations asynchrones, réutilisation) peut briser la garantie. Le compilateur ne prévient pas. Solution : migrez vers weak lors des changements d'architecture ou ajoutez un commentaire d'avertissement.
Résumé
unowned let ou unowned var ; peut être non optionnel et optionnel (Swift 5.0+)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.