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).lazy properties do not work if the structure itself is immutable.lazy value is cached separately for each instance.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"
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.