Ответ
weak-ссылка не увеличивает счётчик сильных ссылок (retain count) объекта в ARC (Automatic Reference Counting). Это ключевое свойство, которое предотвращает циклы сильных ссылок (retain cycles).
Принцип работы:
- Нет удержания:
weak-ссылка не мешает ARC освободить объект, когда на него не остаётся сильных ссылок. - Автоматическое обнуление: После освобождения объекта все
weak-ссылки на него автоматически устанавливаются вnil. Это предотвращает краши при обращении к «висячим» указателям.
Пример:
class Server {
let name: String
init(name: String) { self.name = name; print("(name) создан") }
deinit { print("(name) удалён") }
}
var primaryServer: Server? = Server(name: "Primary") // Retain count = 1
weak var backupServerRef = primaryServer // Retain count остаётся = 1
primaryServer = nil // Сильных ссылок нет. Вывод: "Primary удалён"
print(backupServerRef) // nil. Безопасно, не вызывает краш.
Типичные сценарии использования:
- Делегаты (delegates): Почти всегда объявляются как
weak, чтобы объект не удерживал своего делегата. - Замыкания (closures): Использование
[weak self]для предотвращения цикла, когда self удерживает замыкание, а замыкание удерживает self. - Родительско-дочерние связи: Дочерний объект может иметь
weak-ссылку на родительский.
Важно: weak-ссылки в Swift всегда должны быть опциональными переменными (var) типа, так как они могут стать nil.
Ответ 18+ 🔞
О, смотри-ка, какой умный припёрся с ARC и weak-ссылками! Давай разжуём эту тему так, чтобы даже у кота, который по клавиатуре ходил, мозги не вскипели.
Слушай сюда, мой друг. Представь, что у тебя есть объект — ну, скажем, здоровенный такой сервер, который орет «Я живой!». Пока на него кто-то сильно смотрит (strong reference), он живёт и пыхтит. Но вот появляется эта хитрая жопа — weak ссылка.
В чём её подвох, спросишь ты? А в том, что она — предатель!
Она не увеличивает счётчик сильных ссылок (retain count). Вообще. Ни на йоту. Это как если бы ты крикнул объекту: «Эй, дружище, я тут за тобой наблюдаю, но если тебя начнут убивать — я даже пальцем не пошевелю, спасать не буду». И объект ей верит, сука.
А дальше магия, блядь:
- Не держит. Когда последний сильный ссылочник машет ручкой и говорит «прощай», ARC с чистой совестью отправляет объект в утиль. А weak-ссылка? А ей похуй. Она просто стоит и смотрит, как его деаллоцируют.
- Автоматически обнуляется. И вот тут — гениальность, ёпта! После того как объект стал пылью, weak-ссылка не превращается в ту самую «висячую», от которой крашится всё к хуям. Нет! Она вежливо становится
nil. Как будто так и было. Безопасно, культурно. Обратишься к ней — получишьnil, а не вылет в космос.
Пример, чтобы совсем охуенно стало понятно:
class Server {
let name: String
init(name: String) { self.name = name; print("(name) создан, блядь!") }
deinit { print("(name) удалён в пизду!") } // Прощай, друг
}
var primaryServer: Server? = Server(name: "Primary") // Сильная ссылка. Retain count = 1. Живёт.
weak var backupServerRef = primaryServer // Weak ссылка. Retain count ВСЁ ЕЩЁ = 1. Не держит!
primaryServer = nil // Последняя сильная ссылка ушла. Вывод: "Primary удалён в пизду!"
print(backupServerRef) // nil. Тишина. Спокойствие. Никакого краша.
Где эту штуку впендюривают, чтобы не облажаться?
- Делегаты (delegates): Это святое, ёпта! Объект почти никогда не должен сильно держать своего делегата. Иначе получится «я тебя породил — я тебя и похороню», а делегат уже давно похоронен быть должен.
weak var delegate: SomeDelegateProtocol?— золотое правило. - Замыкания (closures): Вот тут часто все и ебутся. Классика: объект держит замыкание, а замыкание внутри держит
self. Цикл, пиздец, память не освобождается. Спасение —[weak self] in. Говоришь замыканию: «Слушай, наselfможешь ссылаться, но только слабенько, а то сами с усами». - Связи в иерархии: Дочерний объект может слабо ссылаться на родителя, чтобы не мешать тому умереть, когда придёт время.
Важный нюанс, про который все забывают, пока не наступят на грабли:
weak-ссылки в Swift — обязательно опциональные переменные (var). Потому что их состояние — nil или объект — может меняться. Константой (let) её не сделаешь, это же пиздец как логично.