Unowned Reference : ce que c'est, syntaxe et utilisation dans les applications mobiles

Auteur : IT Sectr Publié le : 2026-03-30 Temps de lecture : 9 min

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 « référence non possédée sans remise à zéro automatique ; non optionnel, n'augmente pas le retain count
  • Garantie « utilisée lorsqu'il est garanti que l'objet ne peut pas être libéré avant l'objet qui le référence
  • Différence de weak « unowned ne se remet pas à nil (risque de crash), weak se remet à nil (sûr)
  • Scénarios « parent-enfant avec garantie de vie, closures avec unowned self, singletons et Service Locator
  • Risque « accéder à un objet unowned libéré provoque un crash au moment de l'exécution (EXC_BAD_ACCESS)

Qu'est-ce que Unowned Reference ?

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.

Syntaxe de unowned en Swift

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.

swift
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

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.

Unowned Optional

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.

Unowned vs Weak : quand utiliser quoi

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èreWeakUnowned
OptionnelOui (Type?)Non (Type)
Remise à zéro à la désallocationAuto à nilNon (risque de pointeur pendant)
Type (let/var)Var uniquementlet ou var
PerformanceSurcharge de la table weakMinimale (pointeur simple)
SécuritéSûr (nil vérifié)Risque d'EXC_BAD_ACCESS
Garantie de durée de vieNon requiseGarantie explicite requise

Règle pratique

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.

Unowned self dans les closures

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.

Quand unowned self est sûr

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.

swift
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 }
}

Quand unowned self est dangereux

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].

swift
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).

Risques de unowned et comment les éviter

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.

Refactoring et modification des garanties

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.

Unowned dans les hiérarchies UIKit

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.

Bonnes pratiques

Pour réduire le risque lors de l'utilisation de unowned, suivez ces règles :

  • Préférez weak par défaut « weak est sûr, unowned est une optimisation, pas une norme
  • Documentez les garanties « pour chaque unowned, écrivez un commentaire avec justification
  • Évitez unowned dans ViewController « le cycle de vie UIKit est imprévisible pour les garanties unowned
  • Utilisez unowned uniquement pour les closures synchrones « sorted, filter, map sont des candidats sûrs
  • Vérifiez lors de la revue de code « chaque unowned nécessite une justification de l'auteur du code
  • Migrez vers weak au moindre doute « la perte de lisibilité (un guard let) est moindre qu'un crash en production
swift
// 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

Que se passe-t-il lors de l'accès à une référence unowned après la libération de l'objet ?

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).

Peut-on utiliser unowned avec des protocoles ?

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.

Quand unowned est-il plus sûr que weak ?

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.

Y a-t-il une différence de performance entre unowned et weak ?

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.

Comment le refactoring affecte-t-il les garanties de unowned ?

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 Reference « référence non possédée sans remise à zéro ; non optionnel, n'augmente pas le retain count
  • Garantie « nécessite une preuve explicite que l'objet vit au moins aussi longtemps que le code qui le référence
  • Syntaxe « unowned let ou unowned var ; peut être non optionnel et optionnel (Swift 5.0+)
  • Unowned vs Weak « unowned est plus rapide et plus propre, mais weak est plus sûr ; weak est le choix par défaut
  • Closures « unowned self uniquement pour les closures synchrones ; les asynchrones nécessitent [weak self]
  • Documentation « chaque unowned doit avoir un commentaire justifiant la garantie
  • Recommandation « en cas de doute, choisissez weak ; unowned est pour les contrats explicites et documentés

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