Why do we get strong reference circle in the second example, why we did not in the first example?
class Test1 {
var name: String = "Ted"
lazy var greeting = { return "Hello \(self.name)" }()
deinit{print("goodby1")} // No retain cycle here ..
}
var v1:Test1? = Test1()
v1?.greeting
v1 = nil //prints goodby1, dealocation done
class Test {
var name: String = "Mery"
lazy var greeting = {return "Hello \(self.name)"}
deinit{print("goodby")} //retain cycle here
}
var v: Test? = Test()
v!.greeting
v = nil
In the first example, the closure is executed one time, it returns a String, and that String is assigned greeting. There is no closure; nothing is captured. This is just an anonymous function. If you like, you can get rid of the self., just like in a named function. The key point is that the type of greeting is String.
In the second example, greeting is a closure value, which captures self. Since self holds greeting and greeting holds self, there's a loop. The key point is that the type of greeting is () -> String. This is almost certainly a mistake, since this is not how lazy is intended to be used.
(lazy is a pretty weird feature in Swift, and was probably a bad idea to include in the langauge. I try to avoid it as much as possible. There are several subtle ways to use it incorrectly, so it's not surprising that it's bitten you.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With