Sobes.tech
Middle

Qu'est-ce que le comptage automatique des liens?

sobes.tech IA

Réponse de l'IA

Le comptage automatique des références (Automatic Reference Counting, ARC) est un mécanisme de gestion de mémoire en Swift et Objective-C qui suit et libère automatiquement la mémoire allouée aux objets. Chaque instance de classe possède un compteur de références qui augmente lors de la création d'une référence forte à l'objet et diminue lors de sa suppression. Lorsque le compteur atteint zéro, ARC désalloue automatiquement l'objet et libère la mémoire qu'il occupe.

ARC empêche les fuites de mémoire et les double libérations, simplifiant la gestion de la mémoire par rapport à la gestion manuelle (comme en Objective-C sans ARC).

Il existe trois types de références :

  1. Strong (Fort): Augmente le compteur de références de l'objet. C'est le type de référence par défaut.
  2. Weak (Faible): N'augmente pas le compteur de références. Utilisé pour prévenir les cycles de références fortes, lorsque deux objets se réfèrent mutuellement. La référence faible devient nil si l'objet pointé est désalloué. Définie avec le mot-clé weak.
  3. Unowned (Sans propriétaire): N'augmente pas le compteur de références et a toujours une valeur. Utilisée lorsque l'on sait que la référence pointera toujours vers un objet tant qu'il existe. Contrairement à weak, la référence sans propriétaire ne devient pas nil et peut causer une erreur si l'on tente d'accéder à l'objet après sa désallocation. Définie avec le mot-clé unowned.

Exemple de cycle de références fortes :

class Human {
    let name: String
    var apartment: Apartment? // Référence forte à un Apartment optionnel
    init(name: String) {
        self.name = name
        print("\(name) est en cours d'initialisation")
    }
    deinit {
        print("\(name) est en cours de désinitialisation")
    }
}

class Apartment {
    let unit: String
    var tenant: Human? // Référence forte à un Human optionnel
    init(unit: String) {
        self.unit = unit
        print("Appartement \(unit) est en cours d'initialisation")
    }
    deinit {
        print("Appartement \(unit) est en cours de désinitialisation")
    }
}

var john: Human?
var unit4A: Apartment?

john = Human(name: "John Appleseed")
unit4A = Apartment(unit: "4A")

john!.apartment = unit4A
unit4A!.tenant = john

john = nil
unit4A = nil
// Aucun message de désinitialisation ne sera affiché en raison du cycle de références fortes

Solution au cycle de références fortes avec weak :

class Human {
    let name: String
    var apartment: Apartment?
    init(name: String) {
        self.name = name
        print("\(name) est en cours d'initialisation")
    }
    deinit {
        print("\(name) est en cours de désinitialisation")
    }
}

class Apartment {
    let unit: String
    weak var tenant: Human? // Référence faible
    init(unit: String) {
        self.unit = unit
        print("Appartement \(unit) est en cours d'initialisation")
    }
    deinit {
        print("Appartement \(unit) est en cours de désinitialisation")
    }
}

var john: Human?
var unit4A: Apartment?

john = Human(name: "John Appleseed")
unit4A = Apartment(unit: "4A")

john!.apartment = unit4A
unit4A!.tenant = john

john = nil // John est désalloué, car son compteur de références devient 0
unit4A = nil // Apartment est désalloué, car son compteur de références devient 0