Ответ
Swift (в контексте управления памятью для классов) предоставляет три основных типа ссылок, которые отличаются своим влиянием на счетчик ссылок (Retain Count) и поведением при освобождении объекта.
| Тип ссылки | Влияние на Retain Count | Опциональность | Поведение при освобождении объекта | Типичный use-case |
|---|---|---|---|---|
| Strong | Увеличивает (+1) | Optional/Non-optional | Удерживает объект в памяти. | Стандартная ссылка, владение объектом. |
| Weak | Не увеличивает | Всегда Optional | Автоматически становится nil. |
Для разрыва потенциальных retain cycles (напр., delegate, дочерние ссылки на родителя). |
| Unowned | Не увеличивает | Non-optional | Остается dangling (обращение → краш). | Когда время жизни ссылаемого объекта гарантированно равно или длиннее времени жизни ссылки. |
Примеры и различия:
class Customer {
let name: String
var card: CreditCard? // Сильная ссылка на CreditCard
init(name: String) { self.name = name }
deinit { print("(name) is being deinitialized") }
}
class CreditCard {
let number: String
weak var customer: Customer? // СЛАБАЯ ссылка разрывает цикл
init(number: String, customer: Customer) {
self.number = number
self.customer = customer // Не увеличивает retain count Customer
}
deinit { print("Card #(number) is being deinitialized") }
}
// Использование
var john: Customer? = Customer(name: "John")
john!.card = CreditCard(number: "1234", customer: john!)
john = nil // Customer освобождается, затем CreditCard, т.к. цикл разорван weak-ссылкой.
// Вывод в консоль:
// John is being deinitialized
// Card #1234 is being deinitialized
Unowned (пример с гарантированным временем жизни):
class Department {
let name: String
unowned var manager: Employee // Руководитель не может существовать без отдела
init(name: String, manager: Employee) { ... }
}
Вывод: Используйте weak для безопасного разрыва циклов, unowned — только при абсолютной уверенности в жизненном цикле, чтобы избежать крашей.