Память
October 17

Разрешение цикла сильных ссылок с помощью слабой ссылки

👋 В прошлых статьях мы подробно рассмотрели природу возникновения цикла сильных ссылок с помощью наглядного примера.

🔗 В этой статье я хотел бы рассмотреть пример, как можно использовать слабые ссылки, чтобы избежать таких циклов.

Что такое слабая ссылка?

📖 Слабая ссылка (weak reference) — это ссылка, которая не удерживает сильной привязки к объекту, на который она ссылается. Это означает, что такая ссылка не мешает ARC (Automatic Reference Counting) освобождать объект, на который она указывает. В отличие от сильной ссылки, слабая ссылка не увеличивает счетчик удержания объекта.

Как использовать слабую ссылку?

👉 Для объявления слабой ссылки мы используем ключевое слово weak перед свойством или переменной. Поскольку слабая ссылка не удерживает объект, он может быть освобожден в любой момент, даже если существует слабая ссылка на него.

Следовательно, когда объект, на который ссылается слабая ссылка, освобождается, ARC автоматически присваивает ей значение nil. Из-за этой особенности слабые ссылки должны быть объявлены как переменные, а не константы, что позволяет им изменять свое значение на nil во время выполнения.

Пример использования слабой ссылки

👀 Давайте посмотрим, как слабые ссылки помогают разорвать цикл сильных ссылок.

👉 Возьмем пример с классами Car и Owner. Сделаем свойство car в классе Owner слабой ссылкой.

class Car {
    let brand: String
    var owner: Owner?
    
    init(brand: String) {
        self.brand = brand
        print("\(brand) is being initialized")
    }
    
    deinit {
        print("\(brand) is being deinitialized")
    }
}

class Owner {
    let name: String
    weak var car: Car?
    
    init(name: String) {
        self.name = name
        print("\(name) is being initialized")
    }
    
    deinit {
        print("\(name) is being deinitialized")
    }
}

🔷 Теперь создадим экземпляры этих классов:

var volvo: Car? 
var artem: Owner?

volvo = Car(brand: "Volvo")
artem = Owner(name: "Artem")

🔗 На данный момент у каждого объекта есть по одной сильной ссылке.

🔶 Далее, как и раньше, присвоим значения свойствам:

volvo?.owner = artem
artem?.car = volvo

🚘 В данном случае экземпляр Car по-прежнему имеет сильную ссылку на экземпляр Owner, в то время как экземпляр Owner теперь ссылается на экземпляр Car с использованием слабой ссылки. Это означает, что при обнулении переменной artem, которая указывает на экземпляр Car, сильные ссылки на этот экземпляр исчезнут.

Проверка работы кода

🔶 Чтобы убедиться в этом, сначала установим для volvo значение nil:

volvo = nil

👉 Вывод будет следующим:

Volvo is being initialized
Artem is being initialized
Volvo is being deinitialized

🔶 Как видим, объект Volvo был успешно освобожден.

🔷 Теперь установим artem в nil:

artem = nil

👉 И получим вывод:

Volvo is being initialized
Artem is being initialized
Volvo is being deinitialized
Artem is being deinitialized

🔷 Как видно, при освобождении artem, соответственно, деинициализируется и сам объект Owner.

✨ Надеюсь, данный пример помог вам лучше осознать концепцию слабых ссылок и их применение на практике.

❤️ Ставьте лайк, если хотите, чтобы подобные посты выходили чаще.