BangOperator BangOperator - 5 months ago 31
Swift Question

Lazy initialisation and retain cycle

While using lazy initialisers, is there a chance of having retain cycles?

In a blog post and many other places

[unowned self]
is seen

class Person {

var name: String

lazy var personalizedGreeting: String = {
[unowned self] in
return "Hello, \(self.name)!"
}()

init(name: String) {
self.name = name
}
}


I tried this

class Person {

var name: String

lazy var personalizedGreeting: String = {
//[unowned self] in
return "Hello, \(self.name)!"
}()

init(name: String) {
print("person init")
self.name = name
}

deinit {
print("person deinit")
}
}


Used it like this

//...
let person = Person(name: "name")
print(person.personalizedGreeting)
//..


And found that "person deinit" was logged.

So it seems there are no retain cycles.
As per my knowledge when a block captures self and when this block is strongly retained by self, there is a retain cycle. This case seems similar to a retain cycle but actually it is not.

Answer

I tried this [...]

lazy var personalizedGreeting: String = { [...] }.()

it seems there are no retain cycles

Correct.

The reason is that the immediately applied closure {}() is considered @noescape. It does not retain the captured self.

For reference: Joe Groff's tweet.