Sobes.tech
Middle

Ҳисобкунии худкории пайвандҳо чист?

sobes.tech AI

Ҷавоб аз AI

Автоматичното броене на референции (Automatic Reference Counting, ARC) е механизъм за управление на паметта в Swift и Objective-C, който автоматично следи и освобождава паметта, заделена за обекти. Всеки екземпляр на класа има брояч на референциите, който се увеличава при създаване на силна референция към обекта и се намалява при нейното премахване. Когато броячът достигне нула, ARC автоматично освобождава обекта и паметта, която заема.

ARC предотвратява течове на памет и дублирано освобождаване, опростявайки управлението на паметта в сравнение с ръчното управление (например в Objective-C без ARC).

Съществуват три типа референции:

  1. Strong (Силен): Увеличава брояча на референциите на обекта. Това е подразбиращият се тип референция.
  2. Weak (Слаб): Не увеличава брояча на референциите. Използва се за предотвратяване на цикли на силни референции, когато два обекта се реферират взаимно силно. Слабата референция става nil, ако обектът, към който отива, бъде освободен. Определя се с ключовата дума weak.
  3. Unowned (Безвластен): Не увеличава брояча на референциите и винаги има стойност. Използва се, когато е известно, че референцията винаги ще сочи към обект, докато той съществува. За разлика от weak, безвластната референция не става nil и може да предизвика срив, ако се опитате да достъпите обекта след неговото освобождаване. Определя се с ключовата дума unowned.

Пример за цикъл на силни референции:

class Human {
    let name: String
    var apartment: Apartment? // Силна референция към опционален Apartment
    init(name: String) {
        self.name = name
        print("\(name) се инициализира")
    }
    deinit {
        print("\(name) се деинициализира")
    }
}

class Apartment {
    let unit: String
    var tenant: Human? // Силна референция към опционален Human
    init(unit: String) {
        self.unit = unit
        print("Апартамент \(unit) се инициализира")
    }
    deinit {
        print("Апартамент \(unit) се деинициализира")
}

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
// Нито "John Appleseed се деинициализира", нито "Apartment 4A се деинициализира" ще бъде изведено поради цикъл на силни референции

Решение на проблема с цикъл на силни референции чрез използване на weak:

class Human {
    let name: String
    var apartment: Apartment?
    init(name: String) {
        self.name = name
        print("\(name) се инициализира")
    }
    deinit {
        print("\(name) се деинициализира")
    }
}

class Apartment {
    let unit: String
    weak var tenant: Human? // Слаба референция
    init(unit: String) {
        self.unit = unit
        print("Апартамент \(unit) се инициализира")
    }
    deinit {
        print("Апартамент \(unit) се деинициализира")
    }
}

var john: Human?
var unit4A: Apartment?

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

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

john = nil // John се освобождава, защото неговият брояч на референциите става 0
unit4A = nil // Апартаментът се освобождава, защото неговият брояч на референциите става 0