Sobes.tech
Middle

Ce este numărătoarea automată a linkurilor?

sobes.tech AI

Răspuns de la AI

Numărătoarea automată a referințelor (Automatic Reference Counting, ARC) este un mecanism de gestionare a memoriei în Swift și Objective-C care urmărește și eliberează automat memoria alocată obiectelor. Fiecare instanță de clasă are un contor de referințe care crește atunci când se creează o referință puternică către obiect și scade atunci când aceasta este eliminată. Când contorul de referințe ajunge la zero, ARC de-allocatează automat obiectul și eliberează memoria ocupată.

ARC previne scurgerile de memorie și eliberările duble, simplificând gestionarea memoriei comparativ cu gestionarea manuală (cum ar fi în Objective-C fără ARC).

Există trei tipuri de referințe:

  1. Strong (Puternic): Crește contorul de referințe al obiectului. Este tipul de referință implicit.
  2. Weak (Slab): Nu crește contorul de referințe. Este folosit pentru a preveni ciclurile de referințe puternice, atunci când două obiecte se referă reciproc. Referința slabă devine nil dacă obiectul la care indică este de-allocated. Este definită cu cuvântul cheie weak.
  3. Unowned (Fără proprietar): Nu crește contorul de referințe și are întotdeauna o valoare. Este folosit atunci când se știe că referința va indica întotdeauna către un obiect, atâta timp cât obiectul există. Spre deosebire de weak, referința fără proprietar nu devine nil și poate cauza o eroare dacă se încearcă accesarea obiectului după de-allocare. Este definită cu cuvântul cheie unowned.

Exemplu de ciclu de referințe puternice:

class Human {
    let name: String
    var apartment: Apartment? // Referință puternică la un Apartment opțional
    init(name: String) {
        self.name = name
        print("\(name) este inițializat")
    }
    deinit {
        print("\(name) este de-initializat")
    }
}

class Apartment {
    let unit: String
    var tenant: Human? // Referință puternică la un Human opțional
    init(unit: String) {
        self.unit = unit
        print("Apartament \(unit) este inițializat")
    }
    deinit {
        print("Apartament \(unit) este de-initializat")
    }
}

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
// Nu va fi afișat nici "John Appleseed este de-initializat" nici "Apartament 4A este de-initializat" din cauza ciclului de referințe puternice

Soluție pentru ciclul de referințe puternice folosind weak:

class Human {
    let name: String
    var apartment: Apartment?
    init(name: String) {
        self.name = name
        print("\(name) este inițializat")
    }
    deinit {
        print("\(name) este de-initializat")
    }
}

class Apartment {
    let unit: String
    weak var tenant: Human? // Referință slabă
    init(unit: String) {
        self.unit = unit
        print("Apartament \(unit) este inițializat")
    }
    deinit {
        print("Apartament \(unit) este de-initializat")
    }
}

var john: Human?
var unit4A: Apartment?

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

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

john = nil // John este de-allocated deoarece contorul său de referințe devine 0
unit4A = nil // Apartamentul este de-allocated deoarece contorul său de referințe devine 0