Что меняет объявление сильной ссылки на экземпляр класса через let: сам объект или только возможность переназначить ссылку?
let запрещает переназначить саму ссылку, но не делает экземпляр класса неизменяемым. Если ссылка сильная, она продолжает удерживать объект живым; его изменяемые свойства можно менять через эту ссылку.
В Swift классы используют ссылочную семантику: несколько переменных могут указывать на один экземпляр с общей идентичностью и состоянием. ARC автоматически управляет временем жизни таких экземпляров через подсчёт сильных ссылок, а let и var отдельно определяют, можно ли изменить привязку переменной к объекту.
Такое разделение позволяет запретить замену ссылки, сохранив возможность изменять состояние объекта. Это полезно, когда объект должен оставаться тем же самым экземпляром, но его внутреннее состояние меняется контролируемым API.
Ошибка возникает, когда let трактуют как полную неизменяемость объекта. Тогда кандидат может ошибочно считать, что через константную ссылку нельзя менять свойства класса, либо предположить, что объект перестанет жить после попытки изменить его состояние.
На самом деле нужно различать две операции: изменение самой ссылки и изменение данных экземпляра. Неверное разделение этих понятий приводит к ошибкам в рассуждениях о владении, времени жизни и совместном доступе к объекту.
Сильная ссылка, объявленная через let, владеет экземпляром так же, как сильная ссылка через var. Пока существует хотя бы одна сильная ссылка, ARC не может уничтожить объект. let лишь запрещает присваивание этой переменной другого экземпляра или значения nil.
У класса состояние хранится внутри объекта, а не в самой ссылочной переменной. Поэтому изменяемое stored-свойство можно менять через let-ссылку, если доступ к нему не ограничен модификаторами доступа и само свойство объявлено как var.
В примере counter остаётся сильным владельцем Counter. Изменение value меняет общий экземпляр, а не ссылку. Если другая сильная ссылка указывает на тот же объект, она увидит это изменение.
Для структуры let действует иначе: её изменяемые свойства нельзя менять через константное значение, потому что изменение свойства меняет само значение структуры. У класса же переменная содержит ссылку, поэтому константность ссылки и изменяемость объекта независимы.
Если требуется запретить изменение состояния объекта, одного let недостаточно. Используют доступ только для чтения, делают свойства private(set) или проектируют класс так, чтобы мутирующие операции были недоступны вызывающему коду.
Контроллер получает сервис и сохраняет его в свойстве let. Разработчик ожидает, что сервис станет неизменяемым, но сервис продолжает менять своё состояние во время работы приложения. Замена let на var не решает проблему: она лишь разрешает заменить сам экземпляр и потенциально усложняет контроль владения.
Варианты решения:
let, если контроллер должен работать с одним и тем же сервисом;Обычно выбирают let вместе с ограниченным интерфейсом сервиса. Это сохраняет сильное владение и стабильную идентичность объекта, но не создаёт ложной гарантии неизменяемости его состояния.
let число сильных ссылок по сравнению с var?Нет. Для ARC оба объявления создают сильную ссылку, если не указан другой квалификатор владения. Разница между ними относится к переназначению ссылки: var можно направить на другой объект, а let — нельзя. Время жизни экземпляра определяется количеством и временем существования сильных ссылок, а не тем, объявлена ли ссылка через let или var.
let изменить объект, если на него указывают несколько ссылок?Да, если изменяемое свойство доступно. Все ссылки указывают на один экземпляр, поэтому изменение через одну из них видно через остальные. let не создаёт копию и не делает объект уникальным или изолированным от изменений.
let-ссылки из области видимости?ARC уменьшит число сильных ссылок, когда эта ссылка перестанет существовать, но объект уничтожится только при отсутствии других сильных владельцев. Поэтому выход ссылки из области видимости может вызвать deinit, а может не повлиять на время жизни объекта, если его удерживают свойство, коллекция, замыкание или другая ссылка.