Reputation: 1469
I can see many examples of retain cycles in Swift. However many of them are incorrect, and reading the documentation does not make really simple examples that I can follow.
For the example:
class Dog {
func bark() {
print ("YAP")
}
}
var dog = Dog()
let doSomething = {
dog.bark()
}
doSomething()
Does the closure doSomething cause a retain cycle? I understand that the closure will execute quickly, but that is not the question. Does this inherently cause a retain cycle?
Upvotes: 0
Views: 997
Reputation: 385600
There is no retain cycle in the program you posted.
Consider each object (including each closure) in your program as one vertex in a directed graph. Consider a strong reference from object (or closure) A to object (or closure) B as an edge from A to B in the graph.
A retain cycle is a cycle in the graph: a path containing at least one edge (strong reference) that leads from a vertex back to itself.
For example, a typical retain cycle looks like this:
A view controller always has a strong reference to its view (if the view has been loaded). In this example, the view controller created a closure. The closure captured (has a strong reference to) the view controller. The view controller then stored the closure in a property on the view, creating a retain cycle.
Here's the retain graph of your program:
There are no retain cycles in this graph.
Upvotes: 3
Reputation: 2340
Here is another "example" that runs outside of playground to showcase a retain cycle with a closure:
class ClosureClassStrongRefCycle {
let str : String
lazy var printStr: () -> () = { // self is captured
print("\(self.str)")
}
init(str: String) {
self.str = str
}
deinit {
print("ClosureClassStrongRefCycle is being deallocated")
}
}
Now when you call your class like this :
do {
let myClassWithClosureStrongCycle = ClosureClassStrongRefCycle(str: "closure class strong cycle")
myClassWithClosureStrongCycle.printStr()
} // 'myClassWithClosureStrongCycle' is NEVER deallocated -> Strong reference cycle between this class and it's closure
the instance of ClosureClassStrongRefCycle
retains itself because the closure within it retains self
finally if you want to get rid of the retain cycle, you can add unowned self
like this :
lazy var printStr: () -> () = { [unowned self] in // Unowned copy of self inside printStr
print("\(self.str)")
}
Upvotes: 0