Разрешение цикла сильных ссылок с помощью unowned ссылки
👋 Для разрешения цикла сильных ссылок мы разбирали использование слабых (weak) ссылок. В этом посте мне хотелось бы сосредоточиться на unowned ссылках и их применении.
😁 Стоит отметить, что weak ссылки на русский переводятся однозначно как «слабые». Однако unowned ссылки имеют множество переводов: бесхозные, непривязанные, не принадлежащие и другие. Напишите в комментариях, какой из этих вариантов вам больше по душе!
Что такое unowned ссылка?
🔗 Unowned ссылка представляет собой особый тип ссылки, который не увеличивает счетчик ссылок на объект, что позволяет избежать цикла сильных ссылок.
🔖 В отличие от weak ссылок, unowned ссылки предполагают, что объект, на который они ссылаются, будет существовать на момент обращения к этой ссылке.
⚠️ Важно понимать, что если объект, на который указывает unowned ссылка, был освобожден, приложение вызовет ошибку во время выполнения (runtime error).
Пример использования unowned ссылки
📚 Применение unowned ссылок аналогично тому, как мы работаем со слабыми ссылками.
👤 Давайте создадим класс Customer, в котором будет опциональное свойство car, поскольку у покупателя может и не быть машины.
class Customer { let name: String var car: Car? init(name: String) { self.name = name print("\(name) is being initialized") } deinit { print("\(name) is being deinitialized") } }
🚘 Теперь создадим класс Car, который будет содержать обязательное поле Customer, так как у каждой машины, по нашим предположениям, должен быть покупатель.
class Car { let brand: String unowned let customer: Customer init(brand: String, customer: Customer) { self.brand = brand self.customer = customer print("\(brand) is being initialized") } deinit { print("\(brand) is being deinitialized") } }
👉 Как видно, перед let customer мы добавили слово unowned, что указывает на то, что никто не владеет этой ссылкой, тем самым избегая цикла сильных ссылок.
🔷 Теперь создадим клиента для автомобиля.
var mark: Customer?
🔶 Создадим экземпляр Customer и используем его для инициализации и назначения нового экземпляра Car в качестве свойства машины.
mark = Customer(name: "Mark") mark?.car = Car(brand: "Kia", customer: mark!)
🔷 В этом случае экземпляр Customer получает сильную ссылку на экземпляр Car, а экземпляр Car имеет unowned ссылку на экземпляр Customer.
🔶 Если мы присвоим объекту mark значение nil, то не останется сильных ссылок на экземпляр Customer:
mark = nil
🔷 После этого больше не будет сильных ссылок на экземпляр Car, и он также будет освобожден.
🔶 В результате выполнения кода мы увидим следующий вывод:
Mark is being initialized Kia is being initialized Mark is being deinitialized Kia is being deinitialized
⚠️ Здесь важно учитывать контекст, в котором вы работаете, и быть уверенным в том, что объект будет доступен на момент обращения через unowned ссылку.
✍️ Напишите, пожалуйста, в комментариях, как часто и в каких случаях вы видели использование unowned ссылки в коммерческих приложениях.