Ответ
Weak-ссылка (weak) не создаёт сильного (strong) владения объектом, что помогает избежать циклов сильных ссылок. Её ключевые ограничения:
- Всегда Optional: Поскольку weak-ссылка автоматически становится
nilпри освобождении объекта, она должна быть объявлена как опциональная (weak var delegate: SomeDelegate?). - Только для ссылочных типов: Weak работает исключительно с экземплярами классов (reference types). Для структур и перечислений (value types) она неприменима.
- Отсутствие атомарности доступа: Чтение и запись weak-переменной не являются атомарными операциями. В многопоточной среде объект может быть освобождён между проверкой на
nilи его использованием. - Не гарантирует немедленное обнуление: ARC может обнулить weak-ссылку не мгновенно, а в следующий run loop цикл.
Пример типичного использования для разрыва цикла ссылок:
class ViewController {
weak var delegate: DataProviderDelegate? // Weak, чтобы не удерживать делегата
}
class DataProvider {
var controller: ViewController? // Сильная ссылка
}
// При уничтожении DataProvider, ViewController может быть освобождён,
// так как delegate на него не держит сильную ссылку. Ответ 18+ 🔞
А, слушай, про weak-ссылки, это ж классика, блядь! Ну, типа, чтобы не попасть в просак с этими ебучими циклами удержания, когда два объекта друг за друга цепляются, как два алкаша у подъезда — и оба нахуй не могут разойтись, память жрут!
Смотри, суть проще пареной репы: weak — это как сказать «я тебя знаю, но за тебя не отвечаю, нахер». Сильной хватки нет. И отсюда, блядь, вытекают все её приколы, прям как из пьяного деда:
-
Она всегда Optional, ёпта. Ну логично же! Объект, на который ты слабо ссылаешься, может в любой момент, как последняя надежда, — испариться. И ссылка автоматом станет
nil. Поэтому объявлять надо так:weak var какой-тоМудак: SomeClass?. Не можешь ты weak сделать не-опшинал, это как пытаться удержать воду в решете — нихуя не выйдет. -
Только для классов, блядь! На структуры и енумы даже не смотри — они ж не ссылочные, они по значению живут. Weak — это исключительно для этих зажравшихся ссылочных типов, которые в куче сидят.
-
Атомарности — ноль ебать. Вот это важный момент, многие проёбываются. Читаешь weak-переменную, проверяешь, что она не nil, и тут — бац! — в другом потоке объект приказал долго жить. И ты пытаешься к уже освобождённой памяти обратиться. Пиздец, креш. Между проверкой и использованием всё может ебануться.
-
Мгновенного обнуления не жди. ARC — он не мгновенная справедливость, блядь. Он может weak-ссылку обнулить не прям щас, а в следующем цикле ранлупа. Так что не удивляйся, если объект уже вроде как должен был сдохнуть, а weak-ссылка ещё какое-то время не nil. Жизнь, сука, сложная штука.
Ну и главный кейс, ради которого это всё и затеяно — разорвать ебучую петлю. Смотри, как красота:
class ViewController {
weak var delegate: DataProviderDelegate? // Слабая ссылка. Я делегата вижу, но не душу.
}
class DataProvider {
var controller: ViewController? // А вот это уже сильная хватка, да.
}
Вот и вся магия. DataProvider держит ViewController за горло сильной ссылкой. А ViewController на делегата (DataProvider) только пальчиком слабым показывает: «Вон он». Когда DataProvider решает наложить на себя руки (деинициализироваться), ViewController не держит его сильной ссылкой — weak-то! — и оба спокойно идут на свалку памяти, не заставляя друг друга страдать. Красота, блядь, ебать мои старые костыли!
Вот так-то, а то некоторые думают, что weak — это просто модное слово. Ан нет, хитрая жопа, которая от больших проблем спасает.