In this article, it says (referencing the code below): "You must use lazy to prevent the closure for being created more than once."
private lazy var variable:SomeClass = {
let fVariable = SomeClass()
fVariable.value = 10
return fVariable
}()
Why would lazy prevent the closure from being created more than once? And why would the lack of lazy cause it to evaluate more than once?
The tutorial code you quote is this:
private lazy var variable:SomeClass = {
let fVariable = SomeClass()
fVariable.value = 10
return fVariable
}()
Contrast it with this:
private var variable:SomeClass {
let fVariable = SomeClass()
fVariable.value = 10
return fVariable
}
The first one initializes variable
to a newly created SomeClass instance, once at most (and maybe not even that many times). The second one is a read-only computed variable and creates a new SomeClass instance every time its value is read.
Your intuition is right, that article is incorrect. I'm guessing the author is conflating/confusing computed property syntax with the immediately-executed-closure trick. The lazy
keyword has nothing to do with how many times the closure is executed. lazy
simply causes the property to remain uninitialized until first access, at which point the expression on the right hand side of the equal sign is evaluated.
To simplify, this:
var myVar: MyType {
return MyType()
}
is very different than this:
var myVar: MyType = MyType()
which is similar in storage but has different initialization semantics than this:
lazy var myVar: MyType = MyType()
In the first example, myVar
is a computed property and the code inside of the curly braces is executed every time myVar
is accessed. In other words, every time you access myVar
you'd get a newly created object back.
In the second example, myVar
is a stored property and the expression after the equal sign is evaluated once during initialization of the class or struct that contains that property.
In the third example, myVar
is still a stored property but the evaluation of the expression after the equal sign (be it an initializer expression, a function invocation, or a closure invocation) is delayed until it's accessed.
As a side note, this line of code:
lazy var myVar: MyType = { ... }()
is equivalent to:
func doStuffAndReturnMyType() { ... }
lazy var myVar: MyType = doStuffAndReturnMyType()
The shorthand in the first example wasn't specifically designed for–it just works because Swift's type system (is awesome and) treats closures as unnamed (anonymous) functions.
来源:https://stackoverflow.com/questions/33114865/lazy-variable-with-closure