Ответ
Retain cycle (сильная ссылочная цикличность) возникает, когда два или более объекта удерживают друг друга сильными (strong) ссылками, что предотвращает их освобождение ARC (Automatic Reference Counting). Это приводит к утечкам памяти.
Основные способы решения:
-
weakссылка: Используется, когда один объект не должен "владеть" другим, и ссылка может статьnil(например, делегат).class Parent { var child: Child? } class Child { weak var parent: Parent? // weak разрывает цикл } -
unownedссылка: Используется, когда время жизни ссылаемого объекта гарантированно совпадает или превышает время жизни ссылающегося объекта, и ссылка никогда не должна бытьnil. Обращение кunownedссылке после освобождения объекта вызывает краш.class Customer { let id: String var card: CreditCard? init(id: String) { self.id = id } } class CreditCard { let number: String unowned let customer: Customer // У карты всегда есть владелец init(number: String, customer: Customer) { self.number = number self.customer = customer } } -
Захват списков в замыканиях: Замыкания — это ссылочные типы. Если замыкание, принадлежащее объекту, захватывает
selfсильно, возникает цикл.class NetworkManager { var completion: (() -> Void)? func fetchData() { makeRequest { [weak self] result in // Захватываем self слабо self?.handleResult(result) // self становится опциональным } } }
| Ключевые различия: | Ссылка | Опциональность | Поведение при освобождении объекта |
|---|---|---|---|
strong |
Да/Нет | Удерживает объект в памяти. | |
weak |
Всегда опциональна (T?) |
Автоматически становится nil. |
|
unowned |
Всегда неопциональна (T) |
Вызовет краш при обращении. |
Правило выбора: Используйте weak, если ссылка может стать nil в течение жизни объекта. Используйте unowned, только если вы абсолютно уверены, что ссылаемый объект не будет освобожден раньше.