Sobes.tech
Middle

Mi az automatik hivatkozásszámítás?

sobes.tech MI

Válasz az MI-től

Automatikus hivatkozásszámítás (Automatic Reference Counting, ARC) egy memóriakezelő mechanizmus Swiftben és Objective-C-ben, amely automatikusan nyomon követi és felszabadítja a objektumok számára lefoglalt memóriát. Minden osztálypéldánynak van egy hivatkozásszámlálója, amely növekszik, amikor erős hivatkozás jön létre, és csökken, amikor az megszűnik. Amikor a hivatkozásszámláló eléri a nullát, az ARC automatikusan felszabadítja az objektumot és a memóriát, amit foglalt.

Az ARC megakadályozza a memória szivárgását és a dupla felszabadítást, egyszerűsítve a memória kezelését a kézi kezeléshez képest (például Objective-C-ben ARC nélkül).

Három típusú hivatkozás létezik:

  1. Strong (Erős): Növeli az objektum hivatkozásszámát. Ez az alapértelmezett típus.
  2. Weak (Gyenge): Nem növeli a hivatkozásszámot. Használják az erős hivatkozási ciklusok elkerülésére, amikor két objektum erősen hivatkozik egymásra. Gyenge hivatkozás nil lesz, ha a hivatkozott objektum felszabadul. A weak kulcsszóval van definiálva.
  3. Unowned (Független): Nem növeli a hivatkozásszámot, és mindig értéket tartalmaz. Akkor használják, ha ismert, hogy a hivatkozás mindig egy létező objektumra mutat, amíg az létezik. A weak-hez képest nem lesz nil, és hibát okozhat, ha a felszabadult objektumhoz próbál hozzáférni. Az unowned kulcsszóval van definiálva.

Példa erős hivatkozási ciklusra:

class Human {
    let name: String
    var apartment: Apartment? // Erős hivatkozás egy opcionális Apartmentre
    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? // Erős hivatkozás egy opcionális Humanre
    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
// Sem "John Appleseed is being deinitialized", sem "Apartment 4A is being deinitialized" nem fog megjelenni a ciklus miatt

A probléma megoldása erős hivatkozási ciklus esetén a weak használatával:

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? // Gyenge hivatkozás
    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 felszabadul, mert a hivatkozásszáma 0
unit4A = nil // Az apartman felszabadul, mert a hivatkozásszáma 0