Какова практическая семантика optional unowned-ссылки в Swift?
Optional unowned-ссылка может содержать nil, но не обнуляется автоматически при уничтожении объекта. Она не увеличивает число сильных ссылок, поэтому после уничтожения объекта ненулевое значение такой ссылки становится недействительным; обращение к нему приводит к ошибке времени выполнения.
ARC автоматически управляет временем жизни объектов через сильные ссылки, но не может использовать сильное владение для всех связей: это создало бы циклы удержания. Поэтому Swift предоставляет невладеющие ссылки, позволяющие описывать связи без продления времени жизни объекта.
weak предназначена для ссылок, объект которых может исчезнуть раньше владельца. unowned выражает более сильное предположение: ссылка должна оставаться валидной в течение определённого периода. Optional-вариант нужен, когда такую связь можно явно разорвать, сохраняя при этом невладеющую семантику.
Представим дочерний объект, который хранит ссылку на родительский, но не должен продлевать его жизнь. При этом связь может быть временно отсутствующей или намеренно разорванной.
Если выбрать weak, ссылка автоматически станет nil при уничтожении родителя. Если выбрать optional unowned, разработчик обязан сам поддерживать гарантию валидности ненулевого значения. Ошибка в этой гарантии не превращается в nil, а приводит к аварийному завершению при обращении.
Тип unowned Optional<SomeClass> допускает два состояния самой ссылки: nil и ненулевую ссылку. Однако ненулевая ссылка не является zeroing-ссылкой: ARC не отслеживает её для автоматического обнуления.
В примере child.parent = nil безопасно разрывает связь. Но если parent уничтожится, пока child.parent всё ещё содержит ненулевую ссылку, чтение child.parent будет обращением к уже уничтоженному объекту. Optional здесь не означает автоматическую безопасность: он описывает возможность явного отсутствия ссылки.
Главное отличие от weak таково:
weak не владеет объектом и автоматически становится nil после его уничтожения;unowned не владеет объектом, может быть вручную установлен в nil, но не обнуляется ARC;unowned требует более строгой дисциплины владения и обычно оправдана только при контролируемом жизненном цикле.Такой вариант может быть полезен для двунаправленной структуры, где связь по смыслу необязательна, но её уничтожение контролируется самим кодом. Если невозможно доказать, что ненулевая ссылка всегда валидна до момента чтения, безопаснее выбрать weak.
В редакторе документ создаёт дочерние узлы. Узел должен знать о документе, но не должен удерживать его. При удалении узла связь иногда временно разрывается до привязки к новому документу.
Вариант с weak проще и безопаснее: после уничтожения документа ссылка автоматически станет nil. Недостаток — обращение к weak требует обработки исчезновения объекта, а чтение имеет дополнительные runtime-затраты на zeroing-семантику.
Вариант с optional unowned позволяет явно использовать nil как состояние «узел не привязан» и не требует автоматического zeroing. Но перед уничтожением документа код обязан сначала обнулить ссылки узлов; иначе последующее чтение приведёт к ошибке времени выполнения.
Для обычного приложения выбран бы weak, поскольку жизненный цикл узлов и документа часто меняется из нескольких мест. Optional unowned оправдан только при едином, строго контролируемом владельце, где порядок разрыва связей гарантирован. Это снижает риск аварийного завершения ценой небольшой дополнительной runtime-логики weak.
nil?Нет. Безопасным является только состояние nil. Если ссылка ненулевая, она всё равно предполагает, что объект существует; после его уничтожения optional unowned не станет nil автоматически.
Нет. Такая ссылка не увеличивает счётчик сильных ссылок и никак не препятствует уничтожению объекта. Время жизни определяется сильными владельцами, а optional unowned лишь хранит невладеющую связь.
Когда связь допускает явное состояние nil, но после установки ненулевого значения код может строго гарантировать существование объекта до момента чтения. Если гарантия зависит от сложной логики, конкурирующих потоков или внешних компонентов, weak обычно предпочтительнее: автоматическое обнуление уменьшает вероятность обращения к недействительной ссылке.