Ответ
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, только если вы абсолютно уверены, что ссылаемый объект не будет освобожден раньше.
Ответ 18+ 🔞
А, слушай, смотри, вот эта хрень с retain cycle — это же классика, блядь! Прямо как в анекдоте про двух мужиков, которые держат друг друга за жопу и кричат: «Ты меня отпусти — я тебя отпущу!» А нихуя не отпускают, вот и висят до скончания времён, ебать.
Суть в чём: два объекта хватают друг друга за горло сильными ссылками, и ARC такой: «Ну, раз вы друг другу так нужны — живите вместе вечно, нахуй». А память течёт, как вода из дырявого таза.
Как эту петлю разорвать, чтобы не было мучительно больно:
-
weak— слабая ссылка. Это как сказать: «Я на тебя посмотрю, но если ты сдуешься — ну и хуй с тобой, я не расстроюсь». Используется, когда один объект не должен владеть другим в хардкорном режиме. Типичный пример — делегат. Делегат — он как зритель в театре, а не актёр на сцене.class Папаша { var детёныш: Дитя? } class Дитя { weak var батя: Папаша? // weak! Сын не владеет отцом. Если папа умрёт — сын просто скажет «ну нет и нет». } -
unowned— безусловная ссылка. Это похуистичнее, блядь. Ты говоришь: «Этот объект точно переживёт меня, я в этом уверен, как в том, что хуй — это член». Обращение кunownedссылке после смерти объекта — это гарантированный краш, пиздец и вылет в далёкие ебеня. Используй, только если на 146% уверен.class Клиент { let id: String var карта: Кредитка? init(id: String) { self.id = id } } class Кредитка { let номер: String unowned let владелец: Клиент // Карта не существует без владельца. Это аксиома, ёпта. init(номер: String, владелец: Клиент) { self.номер = номер self.владелец = владелец } } -
Замыкания — вот где собака зарыта и где её чаще всего забывают! Замыкание — это тоже объект, сука. И если замыкание, которое живёт внутри объекта, хватает
selfсильно, получается та самая любовная петля на шее.class СетевойМенеджер { var completion: (() -> Void)? func получитьДанные() { сделатьЗапрос { [weak self] result in // ВАЖНО: захватываем self слабо, как последнюю бутылку пива! self?.обработатьРезультат(result) // И тут self — опциональный, надо через `?` } } }
| Краткая шпаргалка, чтобы не ебал мозг: | Ссылка | Может быть nil? | Что будет, если объект умер? |
|---|---|---|---|
strong |
Да/Нет | Держит мёртвеца в памяти. Призрак, блядь. | |
weak |
Да, всегда! (T?) |
Станет nil. Безопасно и некрашиво. |
|
unowned |
Нет, никогда! (T) |
КРАШ, ёперный театр! Обращение к призраку как к живому. |
Главное правило, чувак: Используй weak, если жизнь ссылки непредсказуема. А unowned — это как игра в русскую рулетку, только вместо револьвера — твоё приложение. Красиво, да?