ProgrammingiOS Developer

What are the key differences of lazy properties in Swift? When should lazy be used, what features and pitfalls exist during their initialization, and how can typical problems be avoided?

Pass interviews with Hintsage AI assistant

Answer.

lazy properties in Swift are calculated only upon their first access. This is often used for resource-intensive objects (e.g., heavy computations, network fetches) that are not needed immediately. They are declared with the keyword lazy:

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

Features and nuances:

  • lazy properties are only allowed for variables (var), not for constants (let).
  • Inside structures, lazy properties do not work if the structure itself is immutable.
  • If set through another thread — it is not thread-safe. One should avoid simultaneous access to lazy properties from different threads.
  • When copying a class object, the lazy value is cached separately for each instance.

Trick question.

Question: "Is the value for a lazy property created during the initialization of the class instance?"

Answer: No, the value is computed only upon first access to the property, not during initialization.

class Expensive { init() { print("init") } } class Example { lazy var heavy = Expensive() } let foo = Example() // does not print anything _ = foo.heavy // now "init"

Examples of real errors due to ignorance of the topic's subtleties.


Story

In a two-platform project, a lazy array (lazy var) was used to store an image cache. Accessing it from multiple threads caused races; they wrapped the lazy var in mutexes — but forgot about lazy, which led to the app crashing.


Story

A young developer tried to declare a lazy let to cache a heavy computation. The code did not compile, as lazy is only allowed for var: it had to rethink the architecture.


Story

The developer declared a lazy property capturing self inside a closure during initialization. This led to a retain cycle — the object was not deallocated even after being removed from all screens.