class Increment {
var number = 0
init(){
print(#function)
}
deinit {
print(#function)
}
// let incrementNumber would give an error — 1
lazy var incrementNumber: (Int) -> () = { [weak self] value in
self?.number = value
print(self?.number)
}
}
do {
let increment = Increment().incrementNumber(3)
}
// output
init()
deinit
nil
if I separate the line, self
is still alive when the closure is executed.
let increment = Increment()
increment.incrementNumber(3)
// output
init()
Optional(3)
deinit
Can anyone please explain why the Increment
get deinit before the incrementNumber()
call?
CodePudding user response:
First of all you need to know definition of lazy variable.
According to apple docs, A lazy stored property is a property whose initial value isn’t calculated until the first time it’s used. You indicate a lazy stored property by writing the lazy modifier before its declaration.
Means that when the class is initial, they don't know they have variable lazy inside which is incrementNumber
.
That the reason when you call
do {
let increment = Increment().incrementNumber(3)
}
Increment
don't recognized incrementNumber
in the class when you access directly. So Swift only see that you do nothing with Increment
class in the rest of code then it automatically deinit
the unused class.
Update: As Mr. DuncanC's mentioned, because of deinit
class first so the compiler create an instance of Increment
as AutoReleased, and keep it in memory in order to evaluate the second part of the expression
At the second, you call
let increment = Increment()
increment.incrementNumber(3)
Means that you make a class at first then you make lazy variable ( Swift sees that you do something with that class in second line so it waits until everything in class is called). Then in the rest of code class Increment
is unused then it automatically deinit
. That's the reason you see lazy is call before deinit
.
For more further knowledge, you can do like making a not lazy function
to see the difference.
class Increment {
var number = 0
init(){
print(#function)
}
deinit {
print(#function)
}
public func increaseNumber(_ value: Int) {
self.number = value
print(#function)
}
}
do {
let increment = Increment().increaseNumber(3)
}
//init()
//increaseNumber(_:)
//deinit
As you can see that increaseNumber
is called before deinit
because the class know that it owns func increaseNumber
so it was called. Then in the rest of code class Increment
is unused then it automatically deinit
.