ПрограммированиеiOS разработчик

В чём ключевые отличия lazy свойств в Swift? Когда стоит использовать lazy, какие особенности и подводные камни существуют при их инициализации, и как избежать типичных проблем?

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

Ответ.

lazy свойства в Swift вычисляются только при первом обращении к ним. Это часто используется для дорогих по ресурсам объектов (например, тяжёлых вычислений, сетевых загрузок), которые не нужны сразу. Объявляются с помощью ключевого слова lazy:

class DataFetcher { lazy var data: Data = self.loadData() func loadData() -> Data { /* … */ } }

Особенности и тонкости:

  • lazy свойства допустимы только для переменных (var), не для констант (let).
  • Внутри структур lazy свойства не работают, если сама структура — immutable.
  • Если set через другой поток — не потокобезопасно. Следует избегать одновременного доступа к lazy-свойствам из разных потоков.
  • При копировании классового объекта, lazy-значение кэшируется для каждого экземпляра отдельно.

Вопрос с подвохом.

Вопрос: "Создаётся ли значение для lazy property при инициализации экземпляра класса?"

Ответ: Нет, значение вычисляется только при первом доступе к свойству, а не при инициализации.

class Expensive { init() { print("init") } } class Example { lazy var heavy = Expensive() } let foo = Example() // ничего не выводит _ = foo.heavy // теперь "init"

Примеры реальных ошибок из-за незнания тонкостей темы.


История

В проекте на две платформы использовался ленивый массив (lazy var) для хранения кэша изображений. При одновременном доступе из нескольких потоков возникали гонки, оборачивали lazy var mutex’ами — но забыли про lazy, что привело к краху приложения.


История

Молодой разработчик пытался объявить lazy let, чтобы кэшировать тяжёлое вычисление. Код не компилировался, так как lazy разрешён только для var: пришлось пересматривать архитектуру.


История

Разработчик объявлял lazy property с захватом self внутри closure при инициализации. Это привело к циклической ссылке — объект не деинициализировался даже после ухода со всех экранов.