Программирование SwiftSwift Coreмладший iOS-разработчик

После освобождения объекта, на который указывает weak ссылка, что произойдёт с этой ссылкой и почему?

После освобождения объекта, на который указывает weak-ссылка, что произойдёт с этой ссылкой и почему?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

weak-ссылка не удерживает объект от освобождения. Когда исчезает последняя сильная ссылка и объект уничтожается, Swift автоматически устанавливает weak-ссылку в nil; поэтому она всегда имеет опциональный тип.

Исторический контекст

ARC автоматизировал управление временем жизни экземпляров классов, но не устранил проблему циклических ссылок. Для связей, в которых один объект должен наблюдать или использовать другой, не продлевая его жизнь, был нужен безопасный тип не владеющей ссылки.

weak решает эту задачу за счёт обнуляемой ссылки: она не увеличивает счётчик сильных ссылок и автоматически становится nil после уничтожения объекта.

Постановка проблемы

Рассмотрим делегат, кэш или владельца временного ресурса. Если такая связь будет сильной, объект может удерживаться дольше ожидаемого или образовать цикл владения, из-за чего ARC не сможет его освободить.

Если вместо weak использовать обычную сильную ссылку, возможна утечка памяти. Если без проверки обратиться к weak-ссылке после уничтожения объекта, логика приложения может ошибочно предполагать, что зависимость всё ещё доступна.

Подробное решение

Объект живёт, пока на него существует хотя бы одна сильная ссылка. weak-ссылка не участвует в подсчёте владения: она лишь отслеживает объект. Когда объект уничтожается, среда выполнения обнуляет все weak-ссылки на него.

Поэтому объявление weak-ссылки требует опциональности. Перед использованием нужно учитывать состояние nil, например через optional binding или optional chaining.

final class Controller { weak var delegate: Delegate? } protocol Delegate: AnyObject { func didUpdate() }

Ограничение AnyObject означает, что такой делегат может быть только экземпляром класса: weak-ссылки применимы к ссылочной семантике, а не к структурам или перечислениям.

weak отличается от unowned. unowned также не удерживает объект, но не обнуляется и предполагает, что объект гарантированно будет жить дольше ссылки. Нарушение этого предположения приводит к аварийному завершению при обращении, тогда как weak даёт безопасный nil, но требует обработки отсутствия объекта.

Ситуация из практики

Экран владеет сервисом загрузки, а сервис уведомляет экран через делегат. Сильная ссылка сервиса на экран создала бы цикл: экран удерживает сервис, сервис удерживает экран, и оба объекта не освобождаются.

Возможны два решения. unowned не требует проверки nil и подходит, если жизненные циклы строго связаны, но ошибка в этом предположении приведёт к аварийному завершению. weak безопаснее для делегата: после закрытия экрана сервис получает nil и прекращает уведомления, однако код должен корректно обработать отсутствие делегата.

Для обычного делегатного отношения выбирают weak. Это предотвращает цикл владения и не требует доказывать, что делегат гарантированно переживёт источник уведомлений.

Что кандидаты часто упускают

1. Почему weak-ссылка обязательно опциональна?

Потому что после уничтожения объекта она должна иметь представимое состояние отсутствия — nil. Неопциональная ссылка не смогла бы корректно выразить тот факт, что объект больше недоступен.

2. Может ли weak-ссылка сохранить объект от уничтожения на время чтения?

Нет. Чтение weak-ссылки не превращает её в владельца. Если объект может быть освобождён конкурентно, локальную сильную ссылку нужно получить в безопасном для конкретной архитектуры месте и затем работать уже с ней; сама weak-ссылка гарантий владения не даёт.

3. Когда предпочтительнее unowned, а не weak?

unowned уместен, когда жизненный цикл ссылки строго подчинён жизненному циклу объекта, например зависимый объект не может существовать без владельца. Он избавляет от optional-проверок, но цена — аварийное завершение при нарушении инварианта. Если жизненные циклы могут расходиться или это сложно гарантировать, предпочтительнее weak.