Удерживает ли Optional, содержащий экземпляр класса, этот экземпляр сильной ссылкой?
Да. Optional, содержащий экземпляр класса в состоянии some, хранит сильную ссылку на него, если сам Optional не объявлен как weak или unowned-ссылка. При переходе в nil эта сильная ссылка освобождается, и объект может быть уничтожен, если других сильных владельцев нет.
ARC был введён в Swift как автоматизация ручного управления подсчётом ссылок. Язык должен одинаково корректно управлять временем жизни объектов независимо от того, хранятся ли ссылки напрямую, в структурах, массивах, Optional или других контейнерах значений.
Optional в Swift — это контейнер-значение, но его payload может быть ссылочным типом. Поэтому контейнер должен учитывать владение объектом так же, как обычное сильное свойство.
Ошибка возникает, когда Optional воспринимают только как возможность отсутствия значения и забывают о семантике хранимого типа. Если в Optional находится экземпляр класса, он обычно продлевает жизнь этого экземпляра.
Из-за этого объект может не уничтожиться после обнуления другой переменной: сильная ссылка всё ещё может находиться внутри Optional, например в свойстве, элементе массива или возвращённом значении. Неправильный вывод о владельцах приводит к поиску несуществующей утечки или, наоборот, к преждевременному освобождению объекта при обнулении последнего Optional.
Optional<T> концептуально содержит либо none, либо some(T). Если T — ссылочный тип, состояние some содержит сильную ссылку на объект.
После присваивания session = nil объект не обязан уничтожаться: его продолжает удерживать backup. Когда backup тоже получает значение nil, сильных ссылок не остаётся, и ARC делает объект доступным для уничтожения.
Важно различать тип переменной и вид ссылки. Запись Session? означает обычную сильную optional-ссылку, а не слабую. Слабость задаётся объявлением самой ссылочной переменной, например свойством weak, а не использованием Optional.
Копирование Optional с экземпляром класса копирует ссылку, а не сам объект. Поэтому два значения Optional могут указывать на один экземпляр и независимо участвовать в его подсчёте сильных ссылок.
Точный момент вызова deinit определяется оптимизацией ARC и последним необходимым использованием значения, а не только концом видимой области видимости. Однако пока сильный Optional семантически нужен программе, объект должен оставаться живым.
В контроллере есть optional-свойство с текущей сессией. После присваивания локальной переменной nil разработчик ожидает вызов deinit, но свойство контроллера всё ещё содержит .some и владеет сессией.
Вариант с обычным Optional корректен, если контроллер действительно должен владеть сессией. Вариант с weak подходит только для ссылки-наблюдателя: он не продлевает жизнь объекта, но требует учитывать возможность nil в любой момент.
Выбранное решение должно исходить из владения, а не из самого факта optional-значения. Если сессия принадлежит контроллеру, оставляют сильное optional-свойство и явно обнуляют его при завершении работы; если контроллер лишь наблюдает за внешним владельцем, используют weak.
Optional число экземпляров класса?Нет. Копируется контейнер и ссылка на тот же объект, но новый экземпляр класса не создаётся. При этом обычное копирование сильного Optional добавляет ещё одного сильного владельца, поэтому уничтожение объекта откладывается до освобождения всех таких значений.
Optional значения nil?Только если это была последняя сильная ссылка и объект не удерживается другими механизмами владения. Дополнительными владельцами могут быть свойства, коллекции, замыкания, параметры вызовов или значения, временно сохраняемые runtime.
T? поведение ссылки с сильного на слабое?Нет. Optional описывает наличие или отсутствие значения, но не режим владения. Переменная типа T? по умолчанию хранит сильную ссылку; для слабой или невладеющей ссылки требуется специальное объявление weak или unowned, применимое к ссылочным переменным и свойствам.