Sobes.tech
Middle

Čo je automatické počítanie odkazov?

sobes.tech AI

Odpoveď od AI

Automatické počítanie referencií (Automatic Reference Counting, ARC) je mechanizmus správy pamäte v Swift a Objective-C, ktorý automaticky sleduje a uvoľňuje pamäť pridelenú pre objekty. Každý inštancia triedy má čítač referencií, ktorý sa zvyšuje pri vytvorení silnej referencie na objekt a znižuje sa pri jej odstránení. Keď čítač referencií dosiahne nulu, ARC automaticky uvoľní objekt a pamäť, ktorú zaberá.

ARC zabraňuje únikom pamäte a duplikovanému uvoľneniu, zjednodušuje správu pamäte v porovnaní s ručnou správou (napríklad v Objective-C bez ARC).

Existujú tri typy referencií:

  1. Strong (Silný): Zvyšuje čítač referencií objektu. Je to predvolený typ referencie.
  2. Weak (Slabý): Nezvyšuje čítač referencií. Používa sa na prevenciu cyklov silných referencií, keď dva objekty navzájom odkazujú jeden na druhý. Slabá referencia sa stáva nil, ak je objekt, na ktorý odkazuje, uvoľnený. Definuje sa kľúčovým slovom weak.
  3. Unowned (Bezvlasť): Nezvyšuje čítač referencií a vždy má hodnotu. Používa sa, keď je známe, že referencia bude vždy ukazovať na objekt, kým existuje. Na rozdiel od weak, bezvlasťová referencia sa nestáva nil a môže spôsobiť pád, ak sa pokúsite pristúpiť k objektu po jeho uvoľnení. Definuje sa kľúčovým slovom unowned.

Príklad cyklu silných referencií:

class Human {
    let name: String
    var apartment: Apartment? // Silná referencia na voliteľný Apartment
    init(name: String) {
        self.name = name
        print("\(name) sa inicializuje")
    }
    deinit {
        print("\(name) sa deinitializuje")
    }
}

class Apartment {
    let unit: String
    var tenant: Human? // Silná referencia na voliteľný Human
    init(unit: String) {
        self.unit = unit
        print("Apartment \(unit) sa inicializuje")
    }
    deinit {
        print("Apartment \(unit) sa deinitializuje")
    }
}

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
// Není zobrazeno "John Appleseed sa deinitializuje" ani "Apartment 4A sa deinitializuje" kvôli cyklu silných referencií

Riešenie problému cyklu silných referencií pomocou weak:

class Human {
    let name: String
    var apartment: Apartment?
    init(name: String) {
        self.name = name
        print("\(name) sa inicializuje")
    }
    deinit {
        print("\(name) sa deinitializuje")
    }
}

class Apartment {
    let unit: String
    weak var tenant: Human? // Slabá referencia
    init(unit: String) {
        self.unit = unit
        print("Apartment \(unit) sa inicializuje")
    }
    deinit {
        print("Apartment \(unit) sa deinitializuje")
    }
}

var john: Human?
var unit4A: Apartment?

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

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

john = nil // John sa uvoľní, pretože jeho čítač referencií sa stáva 0
unit4A = nil // Apartmán sa uvoľní, pretože jeho čítač referencií sa stáva 0