Ответ
Сильная ссылка (strong reference) — это ссылка по умолчанию в Swift, которая увеличивает счетчик ссылок (retain count) объекта в куче. Пока существует хотя бы одна сильная ссылка, объект не будет освобожден.
Пример множественных сильных ссылок:
class Person {
let name: String
init(name: String) { self.name = name; print("(name) инициализирован") }
deinit { print("(name) деинициализирован") }
}
var reference1: Person? = Person(name: "Alice") // Retain count = 1
var reference2: Person? = reference1 // Retain count = 2
var reference3: Person? = reference1 // Retain count = 3
reference1 = nil // Retain count = 2
reference2 = nil // Retain count = 1
reference3 = nil // Retain count = 0 -> Срабатывает deinit
Критическая проблема: Циклы сильных ссылок (Strong Reference Cycle) Возникает, когда два объекта ссылаются друг на друга через сильные ссылки, создавая изолированный граф, который никогда не будет освобожден.
class Person {
let name: String
var apartment: Apartment? // Сильная ссылка на Apartment
init(name: String) { self.name = name }
deinit { print("(name) освобожден") }
}
class Apartment {
let unit: String
var tenant: Person? // Сильная ссылка на Person
init(unit: String) { self.unit = unit }
deinit { print("Апартаменты (unit) освобождены") }
}
var john: Person? = Person(name: "John")
var unit4A: Apartment? = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john // ЦИКЛ: Person → Apartment → Person
john = nil // Объект Person НЕ освобождается (retain count = 1)
unit4A = nil // Объект Apartment НЕ освобождается (retain count = 1)
// ПАМЯТЬ УТЕКАЕТ
Решение: Слабые (weak) и бесхозные (unowned) ссылки
-
weak— не увеличивает retain count. Становитсяnil, когда объект освобождается.class Apartment { weak var tenant: Person? // Решение: слабая ссылка } -
unowned— какweak, но предполагает, что объект существует всегда. При обращении к освобожденному объекту — краш.class Customer { let card: CreditCard init(card: CreditCard) { self.card = card } } class CreditCard { unowned let customer: Customer // Customer всегда существует дольше init(customer: Customer) { self.customer = customer } }
Правило: Используйте weak для опциональных ссылок, которые могут стать nil. Используйте unowned для ссылок, которые всегда имеют значение в течение жизни объекта.