Ответ
weak var используется для объявления слабой изменяемой ссылки с целью предотвращения цикла сильных ссылок (retain cycle). Слабая ссылка не увеличивает счетчик ссылок (retain count) и автоматически становится nil при освобождении объекта.
Основные сценарии использования:
-
Делегаты (Delegates):
protocol ViewControllerDelegate: AnyObject {} class ChildViewController { weak var delegate: ViewControllerDelegate? // Во избежание цикла: родитель -> ребенок -> родитель } -
Замыкания (Closures), захватывающие
self:class DataManager { var onDataUpdated: (() -> Void)? func fetchData() { networkService.requestData { [weak self] data in // Захват `weak self` предотвращает утечку памяти, // если `DataManager` будет освобожден до вызова замыкания. self?.process(data) } } }
Важные правила:
weakприменим только к ссылочным типам (классам).weakссылка всегда должна быть опциональной (var ...?), так как может статьnil.- Использование
weakне гарантирует немедленной деаллокации, но разрывает цикл, позволяя системе освободить память.
Ответ 18+ 🔞
А, ну это же про наши любимые утечки памяти, да? Слушай, вот представь: ты создал объект, он ссылается на другой объект, а тот, блядь, обратно на первый цепляется. И стоят они, обнявшись, как два идиота, и ждут, пока их кто-то отпустит. А никто не отпускает! Это и есть retain cycle, ёпта, порочный круг, из которого хуй выберешься.
Так вот, weak var — это как взять и сказать: «Слушай, я на тебя ссылаюсь, но без фанатизма, я не буду тебя держать силой». Это слабая ссылка, она не увеличивает счётчик владения. И если объект, на который ты слабо ссылаешься, вдруг решит сдохнуть (деаллоцироваться), твоя ссылка просто станет nil. Чисто, аккуратно, без скандалов.
Где это самое слабое звено пригождается?
-
Делегаты, блядь. Классика жанра. Родитель держит ребёнка, а ребёнок хочет держать родителя через делегат. Если держать сильно — получается та самая мертвая хватка, оба в аду.
protocol BossManDelegate: AnyObject {} // Важно! Протокол только для классов. class WorkerAnt { weak var boss: BossManDelegate? // Вот так правильно. Босс может уволиться, а я не буду висеть на нём трупом. } -
Замыкания, эти прожорливые твари. Захватил
selfв замыкании — и привет, цикл. Особенно если замыкание живёт дольше, чем сам объект.class Downloader { var onFinish: (() -> Void)? func startDownload() { someNetworkCrap { [weak self] data in // Захватываем self слабо, как последнего труса! // А внутри уже осторожно распаковываем. self?.handleData(data) // Если self уже нет — просто тихо сдохнем, ничего не делая. } } }
Железные правила, которые нарушать — себя не уважать:
weak— это только для классов. На структуры или енумы не натянешь, они не в той весовой категории.weakссылка — обязательно опционал (var ...?). Потому что её судьба — в любой момент превратиться вnil, и нужно быть к этому готовым.- Это не волшебная таблетка от всех болезней. Это разрыв петли. Дальше система сама разберётся, когда кого прибить. Главное — дать ей такую возможность, а не держать всё в ежовых рукавицах.
Короче, если видишь, что два объекта смотрят друг на друга влюблёнными глазами и не хотят расставаться — вставляй weak. Разводи их, блядь, ради их же блага.