Sobes.tech
Middle

Quels types de liens existent en Swift?

sobes.tech IA

Réponse de l'IA

En Swift, il existe trois principaux types de références aux instances de classes:

  1. Référence forte (Strong Reference):

    • C'est le type de référence par défaut.
    • La référence forte augmente le compteur de références de l'objet.
    • L'objet ne sera pas libéré de la mémoire tant qu'il existe au moins une référence forte.
    • La principale cause de fuites de mémoire dans les cycles de références fortes (strong reference cycles).
    class Person {
        let name: String
        init(name: String) { self.name = name }
        deinit { print("\(name) est en train d'être désinitialisé") }
    }
    
    var reference1: Person? = Person(name: "John")
    // reference1 est maintenant une référence forte, le compteur de références de Person augmente
    
  2. Référence faible (Weak Reference):

    • Déclarée avec le mot-clé weak.
    • La référence faible n'augmente pas le compteur de références de l'objet.
    • Utilisée pour prévenir les cycles de références fortes (strong reference cycles).
    • Toujours optionnelle (Optional), car l'objet pointé par la référence faible peut être détruit à tout moment. Lors de la destruction, la référence faible devient automatiquement nil.
    class Apartment {
        let unit: String
        weak var tenant: Person? // Référence faible
        init(unit: String) { self.unit = unit }
        deinit { print("Appartement \(unit) est en train d'être désinitialisé") }
    }
    
    var john: Person? = Person(name: "John")
    var unit4A: Apartment? = Apartment(unit: "4A")
    
    john?.apartment = unit4A // Si Apartment avait une référence forte à Person
    unit4A?.tenant = john   // Référence faible
    
    // Après suppression des références fortes, les objets seront désinitialisés
    john = nil
    unit4A = nil
    // Sortie: "John est en train d'être désinitialisé", "Appartement 4A est en train d'être désinitialisé"
    // Si tenant était une référence forte, il y aurait fuite de mémoire (cycle fort)
    
  3. Référence non possédée (Unowned Reference):

    • Déclarée avec le mot-clé unowned.
    • Semblable à la référence faible, n'augmente pas le compteur de références de l'objet.
    • Utilisée également pour prévenir les cycles de références fortes.
    • Contrairement à weak, elle n'est pas optionnelle (Optional) et suppose que l'objet pointé existera pendant toute la "durée de vie" de la référence non possédée.
    • Si l'objet pointé par la référence unowned est détruit avant que la référence devienne invalide, une erreur d'exécution (runtime error) se produira.
    • Appropriée dans les situations où un objet existe toujours tant qu'un autre objet lié existe (par exemple, "parent-enfant", où le parent possède l'enfant, mais l'enfant ne possède pas le parent de manière forte).
    class Customer {
        let name: String
        var card: CreditCard?
        init(name: String) { self.name = name }
        deinit { print("\(name) est en train d'être désinitialisé") }
    }
    
    class CreditCard {
        let number: Int
        unowned let customer: Customer // Référence non possédée
    
        init(number: Int, customer: Customer) {
            self.number = number
            self.customer = customer // Assignation sûre en init
        }
        deinit { print("Carte #\(number) est en train d'être désinitialisée") }
    }
    
    var john: Customer? = Customer(name: "John Doe")
    john?.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
    
    // Suppression de la référence forte à Customer
    john = nil
    // Sortie: "John Doe est en train d'être désinitialisé", "Carte #1234567890123456 est en train d'être désinitialisée"
    // La référence non possédée dans CreditCard était valide tant que customer existait.
    // Si CreditCard durait plus longtemps que Customer et qu'on essayait d'accéder à customer via la référence non possédée, une erreur se produirait.
    

Différence clé entre weak et unowned:

  • weak: l'objet peut être nil. Utilisez-le lorsque la durée de vie des objets n'est pas strictement liée (l'un peut exister sans l'autre).
  • unowned: l'objet ne peut pas être nil après l'initialisation. Utilisez-le lorsque vous êtes sûr que l'objet référencé existera au moins jusqu'à ce que l'objet qui le référence existe.