Sobes.tech
Middle

Co je to automatický počet odkazů?

sobes.tech AI

Odpověď od AI

Automatické počítání odkazů (Automatic Reference Counting, ARC) je mechanismus správy paměti v Swift a Objective-C, který automaticky sleduje a uvolňuje paměť přidělenou objektům. Každý instance třídy má čítač odkazů, který se zvyšuje při vytvoření silné reference na objekt a snižuje se při jejím odstranění. Když čítač odkazů dosáhne nuly, ARC automaticky uvolní objekt a uvolní mu přidělenou paměť.

ARC zabraňuje únikům paměti a duplicitnímu uvolnění, zjednodušuje správu paměti ve srovnání s ruční správou (například v Objective-C bez ARC).

Existují tři typy odkazů:

  1. Strong (Silný): Zvyšuje čítač odkazů objektu. Je to výchozí typ odkazu.
  2. Weak (Slabý): nezvyšuje čítač odkazů. Používá se k prevenci cyklů silných odkazů, když si dva objekty navzájem silně odkazují. Slabý odkaz se stává nil, pokud je objekt, na který odkazuje, uvolněn. Definuje se klíčovým slovem weak.
  3. Unowned (Nezávislý): nezvyšuje čítač odkazů a vždy má hodnotu. Používá se, když je známo, že odkaz bude vždy ukazovat na objekt, dokud existuje. Na rozdíl od weak se nezávislý odkaz nestává nil a může způsobit selhání, pokud se pokusíte přistoupit k objektu po jeho uvolnění. Definuje se klíčovým slovem unowned.

Příklad cyklu silných odkazů:

class Human {
    let name: String
    var apartment: Apartment? // Silný odkaz na volitelný Apartment
    init(name: String) {
        self.name = name
        print("\(name) is being initialized")
    }
    deinit {
        print("\(name) is being deinitialized")
    }
}

class Apartment {
    let unit: String
    var tenant: Human? // Silný odkaz na volitelný Human
    init(unit: String) {
        self.unit = unit
        print("Apartment \(unit) is being initialized")
    }
    deinit {
        print("Apartment \(unit) is being deinitialized")
    }
}

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 is being deinitialized" ani "Apartment 4A is being deinitialized" kvůli cyklu silných odkazů

Řešení problému cyklu silných odkazů pomocí weak:

class Human {
    let name: String
    var apartment: Apartment?
    init(name: String) {
        self.name = name
        print("\(name) is being initialized")
    }
    deinit {
        print("\(name) is being deinitialized")
    }
}

class Apartment {
    let unit: String
    weak var tenant: Human? // Slabý odkaz
    init(unit: String) {
        self.unit = unit
        print("Apartment \(unit) is being initialized")
    }
    deinit {
        print("Apartment \(unit) is being deinitialized")
    }
}

var john: Human?
var unit4A: Apartment?

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

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

john = nil // John je uvolněn, protože jeho čítač odkazů je 0
unit4A = nil // Apartmán je uvolněn, protože jeho čítač odkazů je 0