Ответ
weak ссылка автоматически становится nil, когда объект, на который она указывает, деаллоцируется системой управления памятью (ARC). Это основной механизм для разрыва сильных циклов ссылок без риска краша.
Пример с циклом и делегатом:
protocol DataLoaderDelegate: AnyObject { // Протокол должен быть class-bound
func dataLoadingDidFinish()
}
class DataLoader {
weak var delegate: DataLoaderDelegate? // 1. Слабая ссылка на делегата
func loadData() {
// Загрузка данных...
delegate?.dataLoadingDidFinish() // 2. Безопасный вызов через опционал
}
}
class ViewController: UIViewController, DataLoaderDelegate {
let loader = DataLoader()
override func viewDidLoad() {
super.viewDidLoad()
loader.delegate = self // 3. Устанавливаем себя делегатом
loader.loadData()
}
func dataLoadingDidFinish() {
print("Data loaded!")
}
}
// Сценарий:
// 1. ViewController сильно ссылается на DataLoader (свойство `loader`).
// 2. DataLoader слабо ссылается на ViewController (свойство `delegate`).
// 3. Когда пользователь закрывает экран, ViewController деаллоцируется.
// 4. Сразу после этого свойство `loader.delegate` автоматически становится `nil`.
// Цикл сильных ссылок не образовался, утечки памяти нет.
Ключевые отличия weak от unowned: |
weak |
unowned |
|---|---|---|
Всегда опциональна (var). |
Неопциональна (let или var). |
|
| Безопасно обнуляется. | При обращении к деаллоцированному объекту — краш. | |
| Используется, когда время жизни ссылаемого объекта может быть короче. | Используется, когда время жизни ссылаемого объекта точно больше или равно. |
Ответ 18+ 🔞
Слушай, вот это вообще классика, блядь! Просто пиздец как важно понять, а то потом приложение твоё нахуй сольётся, а ты будешь сидеть и чесать репу: "И чё это оно память жрёт, как не в себя?".
Ну смотри, weak — это такая ссылка, которая не держит объект за яйца. Представь, ты держишь воздушный шарик за ниточку — это strong-ссылка. А weak — это как будто ты просто пальцем на него показываешь и говоришь: "Вон он, летит!". Если шарик лопнет (объект деаллоцируется), твой палец просто будет тыкать в пустоту, то есть в nil. И всё, никакого краша, просто пустота. Удобно, блядь!
Вот смотри на этот код, тут вся суть:
protocol DataLoaderDelegate: AnyObject { // Важно! Без `AnyObject` weak-ссылку не сделать, ёпта!
func dataLoadingDidFinish()
}
class DataLoader {
weak var delegate: DataLoaderDelegate? // 1. СЛАБАЯ, Карл! Слабая ссылка.
func loadData() {
// Имитируем какую-нибудь ебучую загрузку...
delegate?.dataLoadingDidFinish() // 2. Вызов безопасный. Если делегата уже нет — просто ничего не произойдёт.
}
}
class ViewController: UIViewController, DataLoaderDelegate {
let loader = DataLoader() // Strong ссылка! ViewController держит loader за жопу.
override func viewDidLoad() {
super.viewDidLoad()
loader.delegate = self // 3. А вот loader на нас ссылается СЛАБО.
loader.loadData()
}
func dataLoadingDidFinish() {
print("Данные пришли, ура!")
}
}
Вот что происходит, когда пользователь, такой мудак, закрывает экран:
ViewControllerдолжен умереть.- Но он же держит
loader! Аloaderдержит его (delegate)! Цикл, блядь, сильных ссылок! Казалось бы, пиши пропало — утечка. - А нихуя! Потому что
delegate—weak. Это как будтоloaderговорит: "Я на тебя только смотрю, но не держу". ViewControllerблагополучно сдыхает в памяти.- ARC такой: "Опа, на
ViewControllerбольше никто сильно не ссылается. В пизду его!". - И сразу после этого свойство
loader.delegateавтоматом, блядь, становитсяnil. Волшебство, ёпта! Цикл разорван, утечки нет, все довольны.
А теперь главное — не перепутай с unowned, а то будет тебе ебаный краш вместо тишины и спокойствия.
weak (слабак) |
unowned (самоуверенный уёбок) |
|---|---|
Всегда опционал (var delegate: Delegate?). Может быть nil. |
Неопционал (let captain: Captain). Всегда должен быть. |
Безопасный. Объект умер — ссылка стала nil. Никаких сюрпризов. |
Опасно-хуёвый. Объект умер, а ты попробуй к нему обратиться — получишь краш с криком "Fatal error: Attempted to read an unowned reference...". |
| Используй, когда непонятно, кто кого переживёт. Например, делегаты. | Используй, только если ты на 150% уверен, что объект, на который ссылаешься, будет жить дольше тебя. Например, [unowned self] в замыкании, которое точно выполнится до смерти self. |
Короче, запомни: сомневаешься — ставь weak. Хочешь экстрима и потом искать, где крашнулось — ставь unowned. В рот меня чих-пых, сколько раз уже на этом обжигались!