Apple has documentation that describes how retain cycles work in closures . This is their example of a closure that does not cause a retain cycle.
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = {
[unowned self] in
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name) is being deinitialized")
}
}
I occasionally like to pass a function definition into callback to try and rid my code of callback hell.
This example is a little contrived but does this cause a retain cycle? Would assigning a function like this to a closure ever cause a retain cycle?
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = self.returnHTML
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
func returnHTML() -> String {
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}
deinit {
print("\(name) is being deinitialized")
}
}
Your example isn't contrived enough, actually. Let's make it simpler:
class C {
lazy var f: () -> () = {
[unowned self] in
print(self)
}
init() {}
func doF() {
self.f()
}
deinit {
print("C is being deinitialized")
}
}
Now let's test it:
let c = C()
c.doF()
Result: When c
goes out of scope, we see "C is being deinitialized".
Okay, but now delete [unowned self] in
. Now when we test it, we don't see "C is being deinitialized". We have a retain cycle.
So yes, you have self
retaining a function that refers to self
, that's a retain cycle. You are right to break the cycle with unowned self
.
(Of course, in my example, I'm taking account of the way your lazy
complicates the picture. If we don't say self.f()
— that is, if we never ask the lazy var
to initialize itself — then of course it doesn't matter what the initializer for f
is: it never gets initialized so there can be no retain cycle. But that is an extremely improbable scenario; if you were never going to initialize the lazy var
then you wouldn't have the lazy var
to begin with.)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.