Влияет ли ссылка unowned на время жизни объекта?
Нет. Ссылка unowned не увеличивает счётчик сильных ссылок, поэтому не продлевает жизнь объекта: экземпляр может быть уничтожен, когда исчезнет последняя сильная ссылка. После этого обращение к обычной unowned-ссылке приводит к runtime-ошибке.
ARC автоматизировал управление памятью на основе подсчёта ссылок, избавив разработчика от ручного вызова операций удержания и освобождения объектов. Однако циклы владения невозможно устранить одним только подсчётом ссылок, поэтому в Swift предусмотрены не владеющие ссылки — weak и unowned.
Они решают разные варианты одной исходной проблемы: объект должен быть доступен по ссылке, но эта ссылка не должна сама удерживать его в памяти.
Если сохранить связь между объектами как сильную, она увеличит количество владельцев и может сформировать retain cycle. Объекты останутся недостижимыми для остального приложения, но ARC не сможет освободить их, поскольку их счётчики ссылок не равны нулю.
unowned устраняет владение, но вводит требование к корректности программы: объект, на который ссылаются, обязан существовать в момент каждого обращения. Если это условие нарушено, безопасная unowned-ссылка не превращается в nil, а аварийно завершает выполнение.
ARC учитывает только ссылки, которые владеют экземпляром. Сильная ссылка увеличивает число владельцев, а уничтожение последней сильной ссылки делает объект доступным для деинициализации. Ссылка unowned в этот подсчёт не входит.
В этом примере session будет освобождён после обнуления последней сильной ссылки независимо от наличия unowned-ссылок на него. Само хранилище unowned сохраняется отдельно и не удерживает экземпляр.
Обычная unowned-ссылка предполагает гарантированное время жизни объекта. Если объект уже уничтожен, обращение к ссылке вызывает ошибку времени выполнения. Вариант unowned(unsafe) не выполняет такую проверку и может привести к неопределённому поведению, поэтому его применение требует ещё более строгого контроля.
В отличие от weak, unowned не является optional и не обнуляется при уничтожении объекта. Выбирайте unowned только при доказуемой гарантии: владелец ссылки переживает объект, либо ссылка используется исключительно пока объект гарантированно жив. Если объект может исчезнуть раньше, нужна weak-ссылка и проверка на nil.
В компоненте приложения вспомогательный объект хранит ссылку на координатор. Координатор создаёт и владеет вспомогательным объектом, а вспомогательный объект обращается к координатору для отправки результата. Сильная обратная ссылка сформировала бы цикл и не позволила бы координатору освободиться.
Рассматривались два решения. weak безопаснее: ссылка станет nil, если координатор исчезнет, но чтение требует optional-логики и связано с дополнительной runtime-обработкой. unowned не добавляет владения и удобнее для обязательной обратной связи, однако обращение после уничтожения координатора аварийно завершит приложение.
Если архитектура гарантирует, что вспомогательный объект не может пережить координатор, выбирается unowned. Если объект может быть передан в другое место, сохранён отдельно или использован асинхронно после уничтожения координатора, правильнее выбрать weak. Результат такого выбора — отсутствие цикла без риска обращения к уже уничтоженному объекту.
Может ли объект быть уничтожен, если на него всё ещё указывает unowned-ссылка?
Да. unowned не является владельцем и не препятствует уменьшению числа сильных ссылок до нуля. Наличие такой ссылки не учитывается ARC при принятии решения об уничтожении экземпляра.
Что произойдёт при обращении к обычной unowned-ссылке после уничтожения объекта?
Программа завершится с ошибкой времени выполнения. В отличие от weak, ссылка не станет nil, поэтому optional-проверка не защищает от этой ошибки. Это делает unowned подходящей только при гарантированно корректном порядке жизни объектов.
Почему в сомнительной ситуации лучше выбрать weak, даже если сейчас время жизни объектов кажется очевидным?
Гарантия может перестать выполняться после добавления асинхронной операции, кэширования, передачи объекта в другой компонент или изменения порядка освобождения. weak обнуляется автоматически и позволяет штатно обработать исчезновение объекта, тогда как unowned превращает нарушение предположения в аварийное завершение.